Why .getjson doesnt work but .ajax does? - javascript

I'm working on Free Code Camp's wiki viewer and trying to figure out the api call. I thought getjson and ajax were equivalent but maybe i'm doing something wrong.
So at first I used this getjson code:
$.getJSON('http://en.wikipedia.org/w/api.php?action=query&list=search&format=json&srsearch=' + search,
function(api){
console.log(api);
}, 'jsonp');
but it returned this error: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
Then I used ajax with the same url:
$.ajax({
url: 'http://en.wikipedia.org/w/api.php?action=query&list=search&format=json&srsearch=' + search,
dataType: 'jsonp',
success: getWiki //just console logs the api
});
and this seemed to return the api call. Can anyone explain why getjson didnt work but ajax did?

You're missing the required callback=? query parameter to force $.getJSON to perform a JSONP request
$.getJSON('http://en.wikipedia.org/w/api.php?callback=?', {
action: 'query',
list: 'search',
format: 'json',
srsearch: search
}, api => {
// response handler
})
See http://api.jquery.com/jquery.getjson/#jsonp

This is my solution also I left an alternative using only JavaScript
NOTE I added this &origin=* param in the url to make it work using this the original jQuery code.
var search = 'php';
var searchURL = 'https://en.wikipedia.org/w/api.php?action=query&format=json&generator=search&origin=*&gsrsearch=' + search;
// Using JSON
$.getJSON(searchURL, function(data){
var read = JSON.stringify(data);
console.log('Using jQuery: ' + read);
}, 'jsonp');
// Using JavaScript
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status == 200) {
callback(null, xhr.response);
} else {
callback(status);
}
};
xhr.send();
};
getJSON(searchURL, function(err, data) {
if (err != null) {
alert('Something went wrong: ' + err);
} else {
var read = JSON.stringify(data);
console.log('Using JavaScript: ', read);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

jQuery ajax drops integer on url

I am using this data...
// Pulled from the button that was hit
var method = document.activeElement.getAttribute('method').toUpperCase();
var url = document.activeElement.getAttribute('url');
Both buttons (methods) have the same url defined... '/user/1'
This is my jQuery AJAX call...
$.ajax({
type: method,
url: url', /* I even hard coded this to make sure what it had to use */
contentType: "application/json; charset=utf-8",
data: $(form).serializeArray(),
error: function (xhr, status) {
alert(xhr.status + ' : ' + url);
}
});
I have discovered that a PUT call truncates the number at the end of the given URL. But it has a trailing SLASH, it's OK.
If I run DELETE, it does what I expect
DELETE: /user/1
If I run PUT, I don;t get what I expect...
PUT: /user
notice the number "1" missing from that url?
I dug around and decided to try native JS... this is what I have...
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
var userInfo = JSON.parse(xhr.responseText);
}
};
xhr.send(JSON.stringify($(form).serializeArray()));
If I run DELETE, it does what I expect
DELETE: /user/1
If I run PUT...
PUT: /user/1
It works.
Yes, I know the URL has the "1" at the end for a PUT because I am sending the variable to the console before AND after the ajax call.
console.log(method + ': ' + url);
Besides, its the same var creation used for the native JS as used for the jQuery.
Now here's the kicker!
If the URL is defined as...
PUT: /user/walter
The name at the end stays.
Any ideas?

JavaScript equivalent for jQuery's $.ajax function

I have the following jQuery code:
dataString = 'test'; // array?
$.ajax({
type: "POST",
url: "tokenize.php",
data: {
data: dataString
},
cache: false,
success: function (data) {
returnedvalue = data;
console.log(data); //alert isn't for debugging
}
});
This jQuery code is working fine, but I want a plain JavaScript version of this code which I'm not able to figure out how to do. I made up this code with help from Stack Overflow only.
I have seen that this can be done using XMLHttpRequest:
var http = new XMLHttpRequest();
var url = "tokenize.php";
var params = "lorem=ipsum&name=binny"; // What will be done here in my case?
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
// Call a function when the state changes.
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(params);
The format of application/x-www-form-urlencoded data is:
key=value&key=value&key=value
Run each key and value through encodeURIComponent to deal with characters that have special meaning or that aren't allowed in the encoding.

jsonp request receives 401 unauthorized

I'm using the select2 plugin to connect with LinkedIn's company search API. What I need is for it to work with jsonp so that I can avoid the "Access-Control-Allow-Origin" error I get with a regular json request [I've confirmed that the json request works when I disable the default security settings in Chrome.]. By "work" I mean I want the jsonp request url to authenticate me just as the json request url is, but I continue receiving a 401 unauthorized error.
I think my problem lies with the "callback" parameter in my url set by jsonp. For instance, the LinkedIn-authenticated company-search url created by json is:
http://api.linkedin.com/v1/company-search?keywords=mcdonalds&oauth_consumer_key=xxx&oauth_nonce=xxx&oauth_signature=xxx&oauth_signature_method=xxx&oauth_timestamp=xxx&oauth_token=xxx
With jsonp it is something like:
http://api.linkedin.com/v1/company-search?callback=jQuery19107866718948353082_1365690327081&keywords=mcdonalds&oauth_consumer_key=xxx&oauth_nonce=xxx&oauth_signature=xxx&oauth_signature_method=xxx&oauth_timestamp=xxx&oauth_token=xxx
The only apparent difference is the "callback=jQuery..." parameter. Here is my JavaScript:
function generateUrl(term) {
(function ($) {
var apiKey = 'xxx';
var apiSecret = 'xxx';
var memberToken = 'xxx';
var memberSecret = 'xxx';
var action = 'GET';
var path = 'http://api.linkedin.com/v1/company-search';
var nonce = '1234';
var timestamp = Math.floor((new Date()).getTime()/1000);
var version = '1.0';
var args = "keywords=" + term;
// var format = 'json';
if (args != '') { args += '&'; }
args += "&oauth_nonce=" + nonce + "&oauth_timestamp=" + timestamp + "&oauth_version=" + version;
OAuthSimple().reset();
this.results = (new OAuthSimple()).sign({
path:path,
action:action,
parameters:args,
signatures:{
'consumer_key':apiKey, 'shared_secret': apiSecret,
'access_token':memberToken,'access_secret':memberSecret}
}
);
}
(jQuery));
return results.signed_url.slice(results.signed_url.indexOf('?') + 1);
}
$("#linkedin").select2({
placeholder: "Search for a company.",
minimumInputLength: 1,
allowClear: true,
ajax: {
url: 'http://api.linkedin.com/v1/company-search',
dataType: 'jsonp',
data: function (term, page) {
return generateUrl(term);
},
results: function (data, page) {
return { results: data.companies.values };
}
},
formatResult: companyFormatResult,
formatSelection: companyFormatSelection,
dropdownCssClass: "bigdrop_3"
});
function companyFormatResult(company) {
return company.name;
}
function companyFormatSelection(company) {
return company.name;
}
Could it have something to do with the syntax of my url parameters? I was having problems when the "keywords" parameter wasn't immediately after "company-search?" in the normal json request, but moving the callback parameter in the jsonp request to the end of the url doesn't seem to help.
Thank you in advance.

How do I get Mercury Editor to redirect to a new resource?

After watching RailsCast #296 about Mercury Editor, I am trying to get the editor to redirect to a newly created resource.
I can already redirect on the client-side using JS and window.location.href=. But for a new resource, I cannot "guess" its URL on the client-side. I need it to be in the server response.
However, the problem is that I don't see the possibility of using the server response in the editor. No matter what the controller renders, the server response is discarded by Mercury instead of used as an argument to my function for mercury:saved.
Is there a way to get around this?
I was able to do this on update by sending a valid JSON string back. I would assume create works the same way. check firebug to make sure you're not getting an error in the jQuery.ajax call that Mercury uses.
posts_controller.rb
def mercury_update
post = Post.find(params[:id])
post.title = params[:content][:post_title][:value]
post.body = params[:content][:post_body][:value]
post.save!
render text: '{"url":"'+ post_path(post.slug) +'"}'
end
mercury.js:
jQuery(window).on('mercury:ready', function() {
Mercury.on('saved', function() {
window.location.href = arguments[1].url
});
});
note: I'm using friendly_id to slug my posts
Redirecting on the server side doesn't work because the save button is just an jQuery.ajax call:
// page_editor.js
PageEditor.prototype.save = function(callback) {
var data, method, options, url, _ref, _ref1,
_this = this;
url = (_ref = (_ref1 = this.saveUrl) != null ? _ref1 : Mercury.saveUrl) != null ? _ref : this.iframeSrc();
data = this.serialize();
data = {
content: data
};
if (this.options.saveMethod === 'POST') {
method = 'POST';
} else {
method = 'PUT';
data['_method'] = method;
}
Mercury.log('saving', data);
options = {
headers: Mercury.ajaxHeaders(),
type: method,
dataType: this.options.saveDataType,
data: data,
success: function(response) {
Mercury.changes = false;
Mercury.trigger('saved', response);
if (typeof callback === 'function') {
return callback();
}
},
error: function(response) {
Mercury.trigger('save_failed', response);
return Mercury.notify('Mercury was unable to save to the url: %s', url);
}
};
if (this.options.saveStyle !== 'form') {
options['data'] = jQuery.toJSON(data);
options['contentType'] = 'application/json';
}
return jQuery.ajax(url, options);
};
So your redirect is sent to the success callback, but the page doesn't actually re-render, as with any successful AJAX request. The author discusses overriding this very function here. It also looks like there might be some room to maneuver here by passing a callback function to save.
Btw, another way to do what #corneliusk suggests is:
render { json: {url: post_path(post.slug)} }
Either way, the response body is passed as an argument to the function in the mercury:saved callback.

I can't to process response to a jsonp request

I have url http://translate.google.ru/translate_a/t?client=x&text=enter text&sl=en&tl=pl
If you will go through this link in response you will have js file
with text:
{"sentences":[{"trans":"wprowadzania tekstu","orig":"enter text","translit":"","src_translit":""}],"src":"en","server_time":80}
I created ajax request
function GoogleTranslateItem(sourceText, langFrom, langTo) {
$.ajax({
url: 'http://translate.google.ru/translate_a/t',
data: { client: "x", text: sourceText, sl: langFrom, tl: langTo },
dataType: 'jsonp',
jsonpCallback: "getData",
success: function (data) {
alert("Success");
}
});
function getData(data) {
var dataJson = data;
alert('bingo');
}
when the answer comes from server. I can't to process it
in browser shows js error.
Syntax error at line 1 while loading:
{"sentences":[{"trans":"вход вых
------------^
expected ';', got ':'
Linked script compilation
How can i process this response?
I think you should take a look at this (http://javascriptweblog.wordpress.com/2010/11/29/json-and-jsonp/)
var jsonp = {
callbackCounter: 0,
fetch: function(url, callback) {
var fn = 'JSONPCallback_' + this.callbackCounter++;
window[fn] = this.evalJSONP(callback);
url = url.replace('=JSONPCallback', '=' + fn);
var scriptTag = document.createElement('SCRIPT');
scriptTag.src = url;
document.getElementsByTagName('HEAD')[0].appendChild(scriptTag);
},
evalJSONP: function(callback) {
return function(data) {
var validJSON = false;
if (typeof data == "string") {
try {validJSON = JSON.parse(data);} catch (e) {
/*invalid JSON*/}
} else {
validJSON = JSON.parse(JSON.stringify(data));
window.console && console.warn(
'response data was not a JSON string');
}
if (validJSON) {
callback(validJSON);
} else {
throw("JSONP call returned invalid or empty JSON");
}
}
}
}
The response from http://translate.google.ru/translate_a/t?client=x&text=entertext&sl=en&tl=pl i JSON, not JSON-P. Accessing JSON-data this way is against the cross-site policies, as the browsers prevent such responses to be returned to the client.
As you are allowed to include scripts from other domains, JSON-P is a way of transfering data as javascript (not JSON). You need to find an API supporting JSON-P (I'm not sure if the Translate API supports JSON-P) or create a proxy on the same domain as your client application to access the JSON data.
Read more about the JSON-P protocol here: http://json-p.org/
To create a proxy, you'll need to implement a service that fetches the content of the Translate API and reprint it in the response.
Example:
/jsonProxy?text=foo
Should return the contents of http://translate.google.ru/translate_a/t?client=x&text=entertext&sl=en&tl=pl
...but you won't have to access it from another domain.
I think the MIME type of the response should be 'application/json'

Categories

Resources