Jquery Ajax - response should replace html - ajax

I'm beginning in Ajax and I have a couples of problems. I have a page with a list containning some video thumbnails, when you rollover on them, there's a "I dislike this" icon showing. That's done. Now where iam having problem is:
When you click that icon, the video title, thumbnail & info should disapear and another video must show.
Here's my Ajax code
function ThumbsDown(id,sort,page) {
$.ajax({
url: "/change/videos/"+id+"/thumbsdown/",
type: "POST",
data: {
"sort": sort?sort:"",
"page": page?page:""
},
complete: function(result) {
// Instead of calling the div name, I need to be able to target it with $(this) and .parent() to make sure only 1 video change, but for now I only want the response to replace the video
$("#content .videoList ul li.videoBox").html(result);
}
});
}
The request is working, im gettin a (200 OK) response. And it's returning me the HTML code block for the new video.
The problem is, when I click the icon, all the html in the div is gone. I have an empty tag, so I guess its interpreted as "empty". But in my firebug .Net tab, I can see clearly that there IS a response.
Any help please? ALREADY FIXED, THANKS
** EDIT **
Now im having problems to target the specific div with$(this) and parents(). Can someone help?
I want to target the li #videoBox
<li class="videoBox recommended">
<div class="spacer" style="display: block;"></div>
<div class="features">
<div>
<a class="dislike_black" title="I dislike this" onclick="ThumbsDown(30835, 'relevance', '1');"></a>
</div>
...
I tried this, and its not working.
success: function(data) {
$("#content .videoList ul li.videoBox").html(data); // this IS WORKING, but replacing ALL the thumbs
$(this).parents("li.videoBox").html(data); // THIS IS NOT
What Im I doing wrong?

The problem you're having, is that you are using the "complete" callback function. This can be misleading, but that callback is meant to be called after a success or a failure. It's more for cleanup, and doesn't receive the response data as you would expect. Basically, all you need to do is change "complete" to "success", and you should receive your expected result.
However, I personally don't suggest using the Ajax function, since it looks like it's entirely unnecessary. The Ajax function exists mostly for complex transactions, and it looks like you have a fairly simple one. What I suggest, is using the "shortcut" function that jQuery provides, like so:
$.post(`/change/videos/${id}/thumbsdown/`, {sort:'', page:''}, function(result){
// Instead of calling the div name, I need to be able to target it
// with $(this) and .parent() to make sure only 1 video change,
// but for now I only want the response to replace the video
$('#content .videoList ul li.videoBox').html(result);
}, 'html');

Change from complete to success
function ThumbsDown(id,sort,page) {
$.ajax({
url: "/change/videos/"+id+"/thumbsdown/",
type: "POST",
data: {
"sort": sort?sort:"",
"page": page?page:""
},
success: function(result) {
// Instead of calling the div name, I need to be able to target it with $(this) and .parent() to make sure only 1 video change, but for now I only want the response to replace the video
$("#content .videoList ul li.videoBox").html(result);
}
});
}
the complete callback unlike the success doesn't get the data parameter, only the jqXHR parameter.

Related

why browser request for image after ajax?

I'm using backbone and nodejs for a single page webapp.
I got a view, which has a model(a blog post) in it. when user click on 'like' button, the view will start ajax send the user'id to server to let the like number +1.
it looks like this:
this.model.save({
likedBy: userModel.get('_id')
}, {
url: '/posts/' + this.model.get('_id') + '/like',
success: function() {
// do something
},
patch: true
});
my problem is, when this code got run. browser start http request to retrieve all the images on the screen, and re-render them. so the screen got a "shake" after user clicked the like button.
this is not happening everywhere, but what caused this? how to stop the "shake"?
thanks for any advance.
When you call this.model.save() the model will update his data in the server and will call your view's render function. The render method will create a new DOM element and replace the old DOM element, that's what causing the flickering (it requests the images again).
I assume you have an API call for Like action (if not it's better to have one) so you can make a sperate AJAX call for like action on your model by adding a function like so:
addLike : function(data) {
Backbone.ajax({
url: '/api/like/'+ this.get('id'),
method: 'POST',
data: data,
success: options.success,
error: options.error
});
}

How do they do this, ajax, json

I have been tasked with adding some functionality to a site similar to this screen on flickr.
Does anyone have any idea how they do the photostream on the right. The images are not in the javascript, json or there is no ajax request.
It would be really useful if anyone had an idea how they did this.
There is an AJAX request performed as you scroll.
Open the console in your browser and look at the network tab. It will show a link similar to this:
http://www.flickr.com/services/rest/?format=json&clientType=yui-3-flickrapi-module&api_key=8800e2eb03db7fb99992039f14061dcf&auth_hash=e65c85db55a2671d8d5968171150c516&auth_token=&secret=9978895fa92da630&photo_id=3396195710&num_prev=4&num_next=0&order_by=&extras=url_sq%2Curl_q%2Curl_t%2Curl_s%2Curl_m%2Curl_z%2Curl_c%2Curl_l%2Curl_o%2Cvideo_size%2Cowner_name%2Cpath_alias%2Cicon_server%2Cneeds_interstitial%2Ccount_comments%2Ccount_faves%2Curl_h%2Curl_k&method=flickr.photos.getContext&jsoncallback=YUI.flickrAPITransactions.flapicb23&cachebust=1358811052893
This is the restful link which returns JSON data. This JSON data contains the urls for the thumbnails of each of the photos, plus other information.
1st There is ajax request when you scroll thumbnails on the right.
And I think that they make an ajax request with the last photo ID in the stream, the next pic in database or prev and the user who uploaded pics and surely others params...
You want a script file that will give you picture thumb encoded in base64, url of the picture and next pictures id in database..
Example
$("#photostream > .scroll").click(function(){
leftOrRight = $(this).attr("id"); // Assume that there is two buttons to get next or previous img with id #next and #prev
$.ajax({
type: "GET",
url: urlOfTheScriptFileThatWillProvideYouData.php, //aspx, jsp ...
dataType: "json",
data: "userId, photoId, leftOrRight",
success: function(yourJson) {
//... Do something with your data and append it in the slider etc..;
},
error: function (xhr, textStatus, errorThrown) {
$("#error").html(xhr.responseText);
}
})
})
Look at URL
http://www.flickr.com/photos/roblawton/3847619643/in/photostream/
http://www.flickr.com/photos/USER-ID/PHOTO-ID/in/photostream/

How to use AJAX as an alternative to iframe

I'm trying to put together a snappy webapp, utilizing JS, Prototype and AJAX for all my requests once the GUI has loaded. The app is simple: A set of links and a container element to display whatever the links point to, just like an iframe. Here's an approximate HTML snippet:
<a class="ajax" href="/somearticle.html">An article</a>
<a class="ajax" href="/anotherarticle.html">Another article</a>
<a class="ajax" href="/someform.html">Some form</a>
<div id="ajax-container"></div>
The JS that accompanies the above (sorry it's a bit lengthy) looks like this:
document.observe('dom:loaded', function(event) {
ajaxifyLinks(document.documentElement);
ajaxifyForms(document.documentElement);
});
function ajaxifyLinks(container) {
container.select('a.ajax').each(function(link) {
link.observe('click', function(event) {
event.stop();
new Ajax.Updater($('ajax-container'), link.href, {
method: 'get',
onSuccess: function(transport) {
// Make sure new ajax-able elements are ajaxified
ajaxifyLinks(container);
ajaxifyForms(container);
}
});
});
});
}
function ajaxifyForms(container) {
console.debug('Notice me');
container.select('form.ajax').each(function(form) {
form.observe('submit', function(event) {
event.stop();
form.request({
onSuccess: function(transport) {
$('ajax-container').update(transport.responseText);
// Make sure new ajax-able elements are ajaxified
ajaxifyLinks(container);
ajaxifyForms(container);
}
});
});
});
}
When clicking a link, the response is displayed in the container. I'm not using an iframe for the container here, because I want whatever elements are on the page to be able to communicate with each other through JS at some point. Now, there is one big problem and one curious phenomenon:
Problem: If a form is returned and displayed in the container, the JS above tries to apply the same behavior to the form, so that whatever response is received after submitting is displayed in the container. This fails, as the submit event is never caught. Why? Note that all returned form elements have the class="ajax" attribute.
Phenomenon: Notice the console.debug() statement in ajaxifyForms(). I expect it to output to the console once after page load and then every time the container is updated with a form. The truth is that the number of outputs to the console seems to double for each time you click a link pointing to a form. Why?
I found another way to achieve what I wanted. In fact, the code for doing so is smaller and is less error prone. Instead of trying to make sure each link and form element on the page is observed at any given time, I utilize event bubbling and listen only to the document itself. Examining each event that bubbles up to it, I can determine whether it is subject for an AJAX request or not. Here's the new JS:
document.observe('submit', function(event) {
if (event.target.hasClassName('ajax')) {
event.stop();
event.target.request({
onSuccess: function(transport) {
$('ajax-container').update(transport.responseText);
}
});
}
});
document.observe('click', function(event) {
if (event.target.hasClassName('ajax')) {
event.stop();
new Ajax.Updater($('ajax-container'), event.target.href, {
method: 'get'
});
}
});
Works like a charm :)

Return false not working for jQuery live

Well this has me well and truly stumped. After searching for the last few hours I still cannot seem to work out where I am going wrong.
I am trying to append an AJAX response to a container when it gets clicked. That works fine but I don't want it to append another object when the elements from the AJAX response also gets clicked.... so:
<div id="container">
<!-- AJAX response to get inserted here, for example -->
<span id="ajaxResponse"></span>
</div>
Here is my script:
$('#container').click(function(e) {
var current_el = $(this).get(0);
$.ajax({
url: 'text.html',
success: function(data) {
$(current_el).append(data);
}
});
return false;
});
So it works fine but for some reason the click event on #container also fires when I click on the AJAX response span!?
According to jQuery documentation:
To stop further handlers from
executing after one bound using
.live(), the handler must return
false. Calling .stopPropagation() will
not accomplish this.
But unless I am mistaken, I am calling false? :(
Anyone help me out on this?
UPDATED:
So the only way I can get it to work is by updating my code to this:
$('#container').live('click', function() {
var current_el = $(this).get(0);
$.ajax({
url: 'text.html',
success: function(data) {
$(current_el).append(data);
}
});
});
$('#ajaxResponse').live('click', function(e) {
return false;
});
This seems a little messy though... anyone have a better solution?
Where is live part you mention in the title of the question ?
It is how the event model works.. If you click on element which does not handle the event, the event will travel up the DOM hierarchy until it finds an element that handles the click (and stops its propagation..). Otherwise you would not be able to put an image inside a <a> tag and click on it..
You can bind a canceling handler on the inner element assuming you have someway to target it..
$.ajax({
url: 'text.html',
success: function(data) {
$(current_el).append(data);
// assuming the returned data from ajax are wrapped in tags
$(current_el).children().click(function(){ return false;});
}
});
I think the return false is referring to something else in this case...
you should try calling stopPropagation() - this should stop the "click" function from propagating down to the ajaxResponse span....
One option that you may want to try is switching over to using live(). Essentially, the click event you setup is calling bind(), and the solution you referenced is using live() which is a variation on bind().
For example:
$('#container').live("click", function(e) {
var current_el = $(this).get(0);
$.ajax({
url: 'text.html',
success: function(data) {
$(current_el).append(data);
}
});
return false;
});
HTH

Can I make an Ajax request inside an ongoing Ajax request (e.g. on the success callback function)?

I have a jQuery application, a shopping cart, that posts back info to the server, if the text inputfield is changed. This is done in an Ajax request. Now, if the Ajaxrequest is a success, I want to reload the shoppingcart asynchronously. The code is as follows:
$(document).ready(function() {
var jInput = $(":input");
jInput.change(function() {
var vareAntal = $(this).val();
var vareID = $(this).siblings("input#vareID").val();
$.ajax({
type: 'POST',
url: 'checkout.aspx',
data: { 'ID': vareID, 'Antal': vareAntal },
success: function() {
$("#newbasket").load(location.href + " #newbasket>*", "");
}
});
});
});
This works, but only once! If I change the text inputfield, after the page is loaded for the first time, the div with the ID of newbasket reloads asynchronously. But if I try to change it again, nothing happens.
I've tried to do some debugging with Firebug, and the first time I change the text inputfield, it fires a POST-event, and afterwards a GET-event, when the POST-event is succesful. But after that, nothing happens when I change the text inputfield again.
So, how do I achieve triggering the .load() method after each text input change?
I've also tried experimenting with the .ajaxComplete() function, but that, of course, resulted in an infinite loop, since the .load() is an ajax-object.
Instead of .change(func), use .live('change', func) here, like this:
jInput.live('change', function() {
This will make the selector work on any new inputs added as well. When you're replacing the elements like you are currently, their event handlers are lost (or rather, not re-created, because you have new elements). .live() is just for this purpose, it listens for events from old and new elements, regardless of when they were added.

Resources