Please could someone help me work out how to get started with JSONP?
Code:
$('document').ready(function() {
var pm_url = 'http://twitter.com/status';
pm_url += '/user_timeline/stephenfry.json';
pm_url += '?count=10&callback=photos';
var photos = function (data) {
alert(data);
};
$.ajax({
url: pm_url,
dataType: 'jsonp',
jsonpCallback: 'photos',
jsonp: false,
});
});
Fiddle: http://jsfiddle.net/R7EPt/6/
Should produce an alert, as far as I can work out from the documentation: isn't (but isn't producing any errors either).
thanks.
JSONP is really a simply trick to overcome XMLHttpRequest same domain policy. (As you know one cannot send AJAX (XMLHttpRequest) request to a different domain.)
So - instead of using XMLHttpRequest we have to use script HTMLl tags, the ones you usually use to load JS files, in order for JS to get data from another domain. Sounds weird?
Thing is - turns out script tags can be used in a fashion similar to XMLHttpRequest! Check this out:
script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://www.someWebApiServer.com/some-data";
You will end up with a script segment that looks like this after it loads the data:
<script>
{['some string 1', 'some data', 'whatever data']}
</script>
However this is a bit inconvenient, because we have to fetch this array from script tag. So JSONP creators decided that this will work better (and it is):
script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://www.someWebApiServer.com/some-data?callback=my_callback";
Notice my_callback function over there? So - when JSONP server receives your request and finds callback parameter - instead of returning plain JS array it'll return this:
my_callback({['some string 1', 'some data', 'whatever data']});
See where the profit is: now we get automatic callback (my_callback) that'll be triggered once we get the data.
That's all there is to know about JSONP: it's a callback and script tags.
NOTE:
These are simple examples of JSONP usage, these are not production ready scripts.
RAW JavaScript demonstration (simple Twitter feed using JSONP):
<html>
<head>
</head>
<body>
<div id = 'twitterFeed'></div>
<script>
function myCallback(dataWeGotViaJsonp){
var text = '';
var len = dataWeGotViaJsonp.length;
for(var i=0;i<len;i++){
twitterEntry = dataWeGotViaJsonp[i];
text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
}
document.getElementById('twitterFeed').innerHTML = text;
}
</script>
<script type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
</body>
</html>
Basic jQuery example (simple Twitter feed using JSONP):
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(document).ready(function(){
$.ajax({
url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
dataType: 'jsonp',
success: function(dataWeGotViaJsonp){
var text = '';
var len = dataWeGotViaJsonp.length;
for(var i=0;i<len;i++){
twitterEntry = dataWeGotViaJsonp[i];
text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
}
$('#twitterFeed').html(text);
}
});
})
</script>
</head>
<body>
<div id = 'twitterFeed'></div>
</body>
</html>
JSONP stands for JSON with Padding. (very poorly named technique as it really has nothing to do with what most people would think of as “padding”.)
There is even easier way how to work with JSONP using jQuery
$.getJSON("http://example.com/something.json?callback=?", function(result){
//response data are now in the result variable
alert(result);
});
The ? on the end of the URL tells jQuery that it is a JSONP request instead of JSON. jQuery registers and calls the callback function automatically.
For more detail refer to the jQuery.getJSON documentation.
In response to the OP, there are two problems with your code: you need to set jsonp='callback', and adding in a callback function in a variable like you did does not seem to work.
Update: when I wrote this the Twitter API was just open, but they changed it and it now requires authentication. I changed the second example to a working (2014Q1) example, but now using github.
This does not work any more - as an exercise, see if you can replace it with the Github API:
$('document').ready(function() {
var pm_url = 'http://twitter.com/status';
pm_url += '/user_timeline/stephenfry.json';
pm_url += '?count=10&callback=photos';
$.ajax({
url: pm_url,
dataType: 'jsonp',
jsonpCallback: 'photos',
jsonp: 'callback',
});
});
function photos (data) {
alert(data);
console.log(data);
};
although alert()ing an array like that does not really work well... The "Net" tab in Firebug will show you the JSON properly. Another handy trick is doing
alert(JSON.stringify(data));
You can also use the jQuery.getJSON method. Here's a complete html example that gets a list of "gists" from github. This way it creates a randomly named callback function for you, that's the final "callback=?" in the url.
<!DOCTYPE html>
<html lang="en">
<head>
<title>JQuery (cross-domain) JSONP Twitter example</title>
<script type="text/javascript"src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script>
$(document).ready(function(){
$.getJSON('https://api.github.com/gists?callback=?', function(response){
$.each(response.data, function(i, gist){
$('#gists').append('<li>' + gist.user.login + " (<a href='" + gist.html_url + "'>" +
(gist.description == "" ? "undescribed" : gist.description) + '</a>)</li>');
});
});
});
</script>
</head>
<body>
<ul id="gists"></ul>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style>img{ height: 100px; float: left; }</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<title>An JSONP example </title>
</head>
<body>
<!-- DIV FOR SHOWING IMAGES -->
<div id="images">
</div>
<!-- SCRIPT FOR GETTING IMAGES FROM FLICKER.COM USING JSONP -->
<script>
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?",
{
format: "json"
},
//RETURNED RESPONSE DATA IS LOOPED AND ONLY IMAGE IS APPENDED TO IMAGE DIV
function(data) {
$.each(data.items, function(i,item){
$("<img/>").attr("src", item.media.m).appendTo("#images");
});
});</script>
</body>
</html>
The above code helps in getting images from the Flicker API. This uses the GET method for getting images using JSONP. It can be found in detail in here
Related
I'm currently trying to learn the basics of Ajax through example. By following a basic tutorial, I've managed to create the following script:
<!DOCYTPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js">
$(function(){
$('#mybtn').on('click', function(e){
e.preventDefault();
$('#mybtn').fadeOut(300);
$.ajax({
url: 'ajax-script.php',
type: 'post',
}); // end ajax call
});
</script>
</head>
<body>
<a href='#' id='mybtn'>click me</a>
</body>
</html>
Combined with a simple php file named ajax-script.php which contains the following code:
<?php
if($_POST) {
echo "<p>ok</p>";
}
?>
Can anyone identify what I might have done wrong? How can I make this work?
You don't have a success function - that's where the echo'd PHP data will be received.
Also, you need to close the script tag that loads the jQuery library, and use a different script tag to delineate the javascript code.
Try this:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$(function(){
$('#mybtn').on('click', function(e){
e.preventDefault();
$('#mybtn').fadeOut(300);
$.ajax({
url: 'ajax-script.php',
type: 'post',
success: function(d){
alert(d);
}
}); // end ajax call
});
</script>
Also, your if ( $_POST ) could cause problems -- either remove that, or post some data:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$(function(){
$('#mybtn').on('click', function(e){
e.preventDefault();
$('#mybtn').fadeOut(300);
$.ajax({
url: 'ajax-script.php',
type: 'post',
data: 'test=Hello',
success: function(d){
alert(d);
}
}); // end ajax call
});
</script>
Then, you could get your PHP to echo what you sent, thus:
<?php
if($_POST) {
$recd = $_POST['test'];
echo 'PHP side received: ' . $recd;
}
?>
To prevent the first answer from becoming too monolithic, I will respond to your comment in this new answer.
A few things to try:
(1) Location of your ajax.php file -- is it in the same folder as the page with the javascript code?
(2) Name of the ajax.php file -- note that in your code it is ajax-script.php
(3) I added an alert after the button click -- did that come up?
(4) I removed the IF condition -- the ajax.php file will echo something back to the javascript success function no matter what.
(5) To ensure that jQuery is working, I added jQuery code to colorize the background. If background not slightly orangish, jQuery is not loading.
Did this fix it?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$(function(){
$('body').css('background','wheat');
$('#mybtn').on('click', function(e){
alert('Button clicked'); //<==========================
e.preventDefault();
$('#mybtn').fadeOut(300);
$.ajax({
url: 'ajax.php',
type: 'post',
data: 'test=Hello',
success: function(d){
alert(d);
}
}); // end ajax call
});
</script>
Then, you could get your PHP to echo what you sent, thus:
<?php
$recd = $_POST['test'];
echo 'PHP side received: ' . $recd;
?>
I am new to Framework7. In this code i am not getting response from Ajax.
Guide me please.
Thanks in advance.
<!-- Path to Framework7 Library JS -->
<script type="text/javascript" src="js/framework7.min.js"></script>
<!-- Path to your app js -->
<script type="text/javascript" src="js/my-app.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script>
var myApp = new Framework7();
var $$ = Dom7;
$$('.form-to-json').on('click', function(){
var name = $$('#name').val();
var password = $$('#password').val();
var data = {"name":name,"password":password};
$$.ajax({
url: "validation.php",
type: "post",
data: data,
//dataType: 'json',
success: function (data)
{
alert("data");
}
});
});
</script>
Validation Page
<?php
echo "Hi";
?>
There's a slight error in your code. In the callback, you are displaying alert("data") which will always display "data". To display what's been sent from the php script, you need to change alert("data") to alert(data).
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
var data = encodeURI("<script>alert('123');</script>");
alert(data);
// Unable to get the alert('123'); in alert due to > symbol
// button click even helps in posting data on backend
$("button").click(function(){
$.post("demo_test_post.asp",
{
name: data ,
city: "Duckburg"
},
function(data,status){
alert("Data: " + data + "\nStatus: " + status);
});
});
});
</script>
</head>
<body>
<button>Send an HTTP POST request to a page and get the result back</button>
</body>
</html>
The problem is that your sequence is not correctly escaped.
try
var data = encodeURI("<script>alert('123');<\/script>");
instead of
var data = encodeURI("<script>alert('123');</script>");
I have a quick question for web professionals.
Supposing I Url-rewrite www.example.com/member.php?id=1 to www.example.com/member/member-name-1
and on member.php I have:
member.php
<html>
<head>
<script type="text/javascript">
function UpdateMember()
{
var member_id = '<?php echo $_GET['id']?>';
$.ajax({
type: "POST",
url: 'update_member.php',
data: {'member_id': member_id},
success: function(response)
{
var d = jQuery.parseJSON(response);
$('#member-details').empty();
$('#member-details').append(d.data);
}
});
}
</head>
<body>
<div id="#member-details"></div>
</body>
</html>
update_member.php
<?php
$respose = "";
if($_POST['id']==1)
$respose = "Content test";
echo json_encode(array('data'=>$respose));
?>
Will Google index the "Content test"? (I believe not)
How can I make it to do so? (I was reading Google's AJAX crawling starter guide, but I'm not sure how that applies to this case: should I change the URL from www.example.com/member/member-name-1 to www.example.com/member/member-name-1#!id=1 ?? Will that work?).
Thanks!!!
I have a html page that displays some basic account information and begins a long-ish running jQuery AJAX request to retrieve more detailed data. While the Ajax request is in progress it is possible for the user to click a button that has an onclick event to navigate to a new page using location.assign.
Unfortunately if the button is clicked before the ajax request is complete nothing will happen until the ajax request completes. This is a live server issue. I want the user to be able to immediately navigate away. FF and Chrome appear to behave better but since this is a corporate intranet application they are not really an option.
The following code is similar to the page in question:
<html>
<head>
<script src="/js/jquery-1.3.2.min.js" type="text/javascript"> </script>
<script type="text/javascript">
<!--
$(function () {
jQuery.ajax({
type: 'GET',
url: '/long-running-partial-html-ajax-endpoint',
success: function (result) {
$('#detail').html(result); });
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
$('#detail').html('Failed to load additional information:<br />' + textStatus + '<br />' + errorThrown);
}
});
});
//-->
</script>
</head>
<body>
<h2>Account Information</h2>
<div>Some basic details here</div>
<div><button onclick="location.assign("/somewhere-else")" type="button">Go somewhere else now</button></div>
<div id="detail">
<img src="/ajax-loading-animation.gif" alt="Loading ..." />
Loading ...
</div>
</body>
</html>
Things I've tried in the debugger (not on live) already:
using a plain anchor rather than a scripted button
using xhr.abort() before the location.assign
put alerts around the location.assign to reassure myself that the code is executing when expected
Observation:
IE stops animating the gif as soon as the button is clicked.
FF/Chrome must automatically abort the ajax request as the jQuery ajax error event is fired
Has anyone come across this issue before? Have you a resolution that will make the navigation more responsive?
Have you tried to call the ajax method after the page is loaded
<body onload="myFunctionThatCallsAjax()">
There are some browser behavior differences when you embed Javascript in the HTML code. Using onload will ensure this is not an issue.
I ended up executing the long running task in a separate thread on the server. The ajax call then just repeatedly calls in to check if a response is ready yet. That way each ajax request is very short.
My solution is fine for a intranet application but would probably need to be made more robust for a Internet application.
So the html becomes:
<html>
<head>
<script src="/js/jquery-1.3.2.min.js" type="text/javascript"> </script>
<script type="text/javascript">
<!--
var detailRequest = null;
function StartDetailRequest() {
detailRequest = jQuery.ajax({
type: 'GET',
url: '<%= Url.Action("EnquiryDetail", "Account", new { requestGuid = ViewData["detailRequestGuid"] }) %>',
success: function (result) {
if (result.length == 0) {
setTimeout("StartDetailRequest()", 500);
}
else {
$('#detail').html(result);
$("table tbody").each(function () { $("tr:odd", this).addClass("odd"); });
}
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
$('#detail').html('Failed to load additional information:<br />' + textStatus + '<br />' + errorThrown);
}
});
}
$(function () {
setTimeout("StartDetailRequest()", 500);
});
//-->
</script>
</head>
<body>
<h2>Account Information</h2>
<div>Some basic details here</div>
<div><button onclick="location.assign("/somewhere-else")" type="button">Go somewhere else now</button></div>
<div id="detail">
<img src="/ajax-loading-animation.gif" alt="Loading ..." />
Loading ...
</div>
</body>
</html>
On the server side I do something like (ASP.NET MVC 2 with pseudo code):
private Dictionary<Guid, DetailRequestObject> detailRequestList = new Dictionary<Guid, DetailRequestObject>();
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string id)
{
var model = GetTheBasicDetails(id);
var request = CreateDetailRequestObject(id);
CheckForTimedOutDetailRequests();
detailRequestList.Add(request.Guid, request);
ViewData["detailRequestGuid"] = request.Guid;
return View(model);
}
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult EnquiryDetail(Guid requestGuid)
{
DetailRequestObject detailRequest = detailRequestList[requestGuid];
if (detailRequest == null)
{
throw new TimeoutException("Timed out retrieving details");
}
else if (!detailRequest.IsComplete)
{
return Content("");
}
else
{
var details = detailRequest.Response();
return PartialView(details);
}
}
The DetailRequestObject class encapsulates the creation of a separate thread using the async model of your choice, sets a flag when complete and collects the response data.
I also have a method CheckForTimedOutDetailRequests that collects requests that have timed out for retrieving so that any that have been 'aborted' can be cleared up.
I think I would prefer to have the long running requests run in a separate Windows Service that would do it's own clean-up, request throttling and such but the above works so...