I have a table with items and a button for to delete each item(row).
For that I built following ajax function:
$(document).ready(function() {
$(".destroy-device").click(function(e) {
e.preventDefault();
var id = $(this).attr("data-id");
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
}
});
$.ajax({
url: 'device/destroy/'+id,
type: 'post',
data: {
_method: 'delete',
id: id
},
success:function(data) {
if($('.form-destroy').attr("data-form-id") == id) {
$('.form-destroy[data-form-id='+id+']').closest("tr").remove();
}
}
});
});
});
I delete the device from my database and remove the row in my html (DOM), but the .remove() function acts slow. After I click on my delete button the row disappears after 1-2 seconds, what could be the cause of this?
On the client side (JavaScript code) there is nothing that visibly slow down execution.
Said that remove() on the row is executed only once the success response is received back from the server.
If the time needed for the ajax request to be sent, processed by the server and the success response sent back to the client takes 1-2-n seconds then the row will disappear not before that amount of time.
Using the browser inspector I would check how much time actually the response takes to come back.
If that's the issue you have two options:
1
let the server operate faster. How to do that is beyond the scope of the question of course.
2
accept the server "latency" and improve the interface to let the user have a better experience.
It's not unusual to have a task to take 1-2 seconds to perform.
Once the button is clicked you may "gray out" the row or show some elements that let the user guess an operation is ongoing.
Upon success remove the row.
Upon failure (an option that your code should handle) reset the row to the original state.
Side note: as per comments, it seems there is something wrong with your if statement.
After I click on my delete button the row disappears after 1-2
seconds, what could be the cause of this?
My bet is thats because it takes 1 - 2 seconds before the ajax calls reaches the success callback. You can check the response time in the console. For (chrome) Just press F12 then goto the network tab.
Little workaround
You can hide the tr element right after the click event.
$('.form-destroy[data-form-id='+id+']').closest("tr").hide();
Then remove it in the success callback in the ajax call. (shoudn't there be a success error check?)
If the above is not a solution for you, you have to improve the speed of your server.
Alternativly
If you just want the user to get a smooth experience, you can also add a little loader animation at the left or right side of the table-row. Then the user knows something is happening. Else he might think that he misclicked.
Something like this perhaps:
A risky but more user friendly way would be hiding the row from the DOM before you've removed it from the Database.
If you do encounter any errors you would have to add it again.
Related
pre1: the explanation of my problem is just an example - not the real situation
pre2: all ajax is asynch
pre3: I don't want to discuss errors / error handling with ajax
Please, imagine I have a simple page with some images of fruits, lets say an apple (of course), an orange and a 42fruit.
When the user clicks one of this images the amount of the fruit is in- or decreased, depending if upper half or lower half of the image.
The "users wish" is sent to the server via ajax, and committed via ajax respond - click by click
To avoid something like a "race", when the user clicks the apple, the apple -image is disabled, until the apple-ajax is finished. (same for others)
so far - no prob.
Now I let the user enter the fruits name in a text box and press '+' or '-' to increase or decrease the amount
If I disable the input until the ajax is ready, all is good, but the user can't enter a new fruit name during this time (or not enter '+/-')
What I would do in other languages is: use a 'named mutex', saying "sorry user - apple update is in progress; choose an other fruit ..."
but how to do that with javascript? (w/o just looping and blocking)
When you do ajax in javascript you have the option of executing code:
During the call
Once the call completes
Once the call errors out
So what you would want to do is when the call is made, disable the inputs. Once the call is complete you will re-enable the boxes (assuming a successful call). An example is as follows in AngularJS (it is very similar for all other languages):
$scope.myData.doClick = function(item, event) {
//Disable the button here
var responsePromise = $http.get("/angularjs-examples/json-test-data.jsp");
responsePromise.success(function(data, status, headers, config) {
//Re-enable the button here
});
responsePromise.error(function(data, status, headers, config) {
alert("AJAX failed!");
});
}
Here is another example in JQuery which will likely be more useful for you:
$("button").click(function(){
//Put your code to disable the button here
$.ajax({url: "demo_test.txt", success: function(result){
//Put your code to re-enable the button here
}});
});
So in the above code you can see that you have the option of calling a given function on success. So you disable the button and then re-enable it once it succeeds.
Preface
For this question, I have a MVC partial view. The view has a section which displays a list of documents. Each document has a hyperlink: when clicked, the hyperlink takes the user to a second page view displaying additional information.
The link is inside an unordered list:
<a style="text-decoration:underline;" onclick="sendToDocketSearch('#currentDocument.DktYear','#currentDocument.DktSequence','#currentDocument.DktSubActionID');">#currentDocument.DktYear.ToString().PadLeft(2, '0') - #currentDocument.DktSequence.ToString().PadLeft(5, '0')</a>
When the user clicks the link, it takes them to a sendToDocketSearch javascript function (to prepare to search for the document):
var sendToDocketSearch = function (yearOfDocket, sequenceOfDocket, dktSubActionIDOfDocket) {
jQuery.ajax({
type: "POST",
url: "#Url.Action("DocketSearchOnDemand")",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ docketYear: yearOfDocket,
docketSequence: sequenceOfDocket,
DktSubActionID: dktSubActionIDOfDocket,
userIsAuthorized: '#Model.userIsAuthorized' }),
success: function (data) {
alert(data);
},
failure: function (errMsg) {
alert(errMsg);
}
});
submitForm();
}
Note that the page/view/form is submitted after the following controller method is run:
public ActionResult DocketSearchOnDemand(string docketYear, string docketSequence, decimal DktSubActionID, bool userIsAuthorized, PortalIndexView viewmodel)
{
System.Web.HttpContext.Current.Session.Add("userIsAuthorized", userIsAuthorized);
string docketSearch = docketYear + "-" + docketSequence;
System.Web.HttpContext.Current.Session["DocketSearchOnDemand"] = docketSearch;
if (DktSubActionID > 0)
{
System.Web.HttpContext.Current.Session["DktSubActionID"] = DktSubActionID.ToString();
System.Web.HttpContext.Current.Session["searchingCustomID"] = true;
}
else
{
System.Web.HttpContext.Current.Session["DktSubActionID"] = "1";
System.Web.HttpContext.Current.Session["searchingCustomID"] = false;
}
return View(viewmodel);
}
The above controller method runs; then, because the form is submitted, the HttpPost action for the page takes place. When running it on my local PC, the link is clicked and the next page is loaded without drama.
Problem
The problems start when I upload the code to the dev/test server. I don't know how to use breakpoints while troubleshooting an active website, so I follow along with the browser developer tool to monitor network traffic.
When clicking the link when running the website on my localserver, the process continues:
the hyperlink takes me to a method where I pass information to be searched
the page/view/form is submitted
the controller redirects where I have to go.
When I click the link on the site and it's on the server, the first click is completely ignored - network traffic shows that it tries to navigate to the controller via the javascript function above, but the failure happens so fast I can't even take a screenshot of it. The page reloads a second time at this point.
When I click on the same link a second time, it works without fail.
I believe the view/javascript/controller code works because it works the second time (and on subsequent attempts). It just flagrantly fails the first time on the server; after that, the user is fine. I'd like to prevent that "first-time" failure, however, and I'm wondering what the problem could be...
Bad timing
I may be passing the information too early (or too late for my website/server to process it properly). The page does it correctly the second time, so maybe I'm just "jumping the gun" by not waiting a little longer for page-loading processes to sort themselves out. (Maybe I can fiddle around with the $(document).ready() javascript portion of the first page to "delay" allowing people to click a link.)
Code error
I'll be glad to admit bad code if I'm genuinely messing something up. Maybe it's my javascript function, or maybe it's the code in my controller; at any rate, something is making the first pass of that function call be rejected. Maybe my code is bad because the problem doesn't happen the second time, and I'm getting a false sense of security (i.e. there are problems with my code that the system is willing to forgive after the page has thoroughly loaded).
Server problem/miscellaneous
I'm wondering if I missed something when I uploaded my latest changes, or if I should have contacted my network team in case there are permissions that need to be activated for the site to work smoothly. I'm already in touch with them regarding something else, so I might take advantage of the opportunity today.
There is an alternative in place that could help me prevent this problem from happening, but I want to find out why the "first-time" failure happens. Other similar actions fail the first time on the site, and I'd like to apply the insights from fixing this issue to them.
Thank you for looking at this issue. Have a great day.
Are you sure you want to call submitForm(); before your jQuery.ajax has finished? your ajax call is async so it will hit submitForm(); before it has had time to finish. should submitForm(); be in your success event instead?
This question already has answers here:
Fire Greasemonkey script on AJAX request
(2 answers)
Closed 3 years ago.
I'm using greasemonkey with Firefox to alter what content is displayed when I visit a particular domain. One of the pages contains a dropdown with two elements, let's call them element0 and element1. Whenever it detects a switch from one to the other, it performs an ajax query that alters the page content depending on which one you've selected. So it looks something like this:
$(".dropdown").change(function(){
if($(this).val()=='element0'){
$.ajax({
// fetch some html
});
}
else{
$.ajax({
// fetch some other html entirely
});
I'm happy with what is displayed when element0 is selected - it's element1's associated content I want to alter. So I need a way to trigger my own userscript function only in the second case. I also somehow need it to execute only after the ajax query is complete of course. How do I do this?
I have some basic experience with programming, but know absolutely nothing about jquery, ajax, json etc etc. A friend helped me locate the above ajax for that page so that I could even post a meaningful question. Please bear my level of experience in mind, because I'd really really like to move forward with whatever knowledge/wisdom you guys can offer, but will only be able to do so if I understand it.
Many thanks!
EDIT: The above is javascript that the host is running. I accessed it by saving the page and looking around manually. I am writing userscripts on the client side to alter what my browser displays. So I want to write my own function that responds to their js in the way I described.
AJAX
In ajax you have a tow useful method,
success & compleate
success: with execute if ajax request are work truth
complete: are work when finished ajax function, so you can use this method
example:
complete: function(){
// call another ajax, hide somthing, do any somthing
},
another example:
var all_data = {'user':txtuser,'pass':txtpass};
$.ajax ({
url:"ajax.php",
type:"post",
data:all_data,
beforeSend:function(){
// do somting before send a data
},
statusCode:{
404:function(){
$("#ma").html("Page not found");
},
401:function(){
$("#ma").html(".....");
}
},
success:function (data) {
$("#ma").html(data);// if sucsess
},
complete:function(){ // when complete
$("#user").hide(2000);
$("#pass").hide(2000);
$(".q").hide(2000);
}
});
I have a situation where I need to increase the number of time article has been read.
Once someone opens an article it should be reflected in the database by incrementing number of reads by one. Simple.
Sending POST request to the server increments the number of reads by one. The article in question is supplied via URL parameter.
Doing it manually by typing the URL in a browser works as expected. So server side is not at fault.
My problems start with the javascript side of it or rather jquery. I hook the event to the article link. So every time a user clicks on the article link it increments the number of reads like so:
$('#list-articles .article-link').click(function(e){
var oid = $(this).parent().parent().attr('data-oid').toString(); //Get the article id
$.post( "/articles/viewed/" + oid );
});
Now this does not work! Number is not increased.
I don't prevent default action since I need the link to actually open and display the article.
Now if I put an alert right after the post like this:
$('#list-articles .article-link').click(function(e){
var oid = $(this).parent().parent().attr('data-oid').toString(); //Get the article id
$.post( "/articles/viewed/" + oid );
alert(oid);
});
This variant works. After I dismiss the alert window, the number is incremented. Why is this so?? How can I fix this to actually work without the alert event present?
UPDATE
Thank you for helping to solve this. All answers are great and help one way or another. The only variant that works so far is disabling async on ajax call. It would be great if someone could elaborate on why switching the async mode off in ajax fixed it. So the post request in the original was never executed? If I was simply checking too early and the number increase was not visible upon page load, it should be still visible on the next page reload, right? SInce it wasn't updated on the database at all I assume that post was not run at all. Why is this so? I want to understand the issue so I do't get into this problem again. Thanks.
Your problem could be due to $.post being asynchronous and you checking this too soon and try posting synchronously:
$.ajax({
type: 'POST',
url: "/articles/viewed/" + oid,
async:false
});
Prevent default. Wait for the response from the server to say incrementing article reads by 1 was successful, then redirect to the article.
If it works with the alert in place it sounds like a race condition.
I use Jquery-ajax calls to post information to a page and display the returned info. The problem I encounter is the following:
When a user makes the first ajax call everything seems normal. When a user does not reload the page and makes the same request for a second time the post-call is made 2 times and the get-call as well. The 3th time there are 4post+4get requests. 4th time 8Post/8Gets. And so on.. until the browser (firefox latest v.) freezes for a while.
I'm a beginning programmer and I don't know what the cause might be. I don't know where to look inside my code. Prehaps you guys can give me a hint. My other ajax requests are fine and only post+get once.
Firebug log:
This is a piece of my code:
$(document).ready(function() {
$('#datepicker').change(function()
{
sendDate($('#datepicker').val());
});
});
function sendDate(str)
{
$.ajax(
{
type: "POST",
url: "manage_processor.php",
data: { chosendate: str },
success: function(data)
{
$('#printdiv').html(data);
}
});
}
Hope anyone can shine some light on this situation.
If I might venture a guess, I suspect the returned data contains a script tag referencing your javascript file. This would explain the GET request you are seeing. Every time the request data is put into #printdiv your script is loaded again and an identical javascript handler would be bound to the same event. This would explain the number of handlers doubling after every request.
Quick test: put console.log( 'script loaded' ); at the top of manage_functions.js. If I'm right it will log after every request.