Increment the number of times an article has been read - javascript

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.

Related

Ajax Jquery remove function is slow

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.

ASP.NET MVC/jQuery/AJAX: link fails to work first time, but works second time (after page reloads)

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?

Jquery ajax calls increase exponential on each request

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.

How to update/modify webpage content with Javascript before page load completed?

I'm trying to display a progress bar during mass mailing process. I use classic ASP, disabled content compression too. I simply update the size of an element which one mimics as progress bar and a text element as percent value.
However during the page load it seems Javascript ignored. I only see the hourglass for a long time then the progress bar with %100. If I make alerts between updates Chrome & IE9 refresh the modified values as what I expect.
Is there any other Javascript command to replace alert() to help updating the actual values? alert() command magically lets browser render the content immediately.
Thanks!
... Loop for ASP mail send code
If percent <> current Then
current = percent
%>
<script type="text/javascript">
//alert(<%=percent%>);
document.getElementById('remain').innerText='%<%=percent%>';
document.getElementById('progress').style.width='<%=percent%>%';
document.getElementById('success').innerText='<%=success%>';
</script>
<%
End If
... Loop end
These are the screenshots if I use alert() in the code: As you see it works but the user should click OK many times.
First step is writing the current progress into a Session variable when it changes:
Session("percent") = percent
Second step is building a simple mechanism that will output that value to browser when requested:
If Request("getpercent")="1" Then
Response.Clear()
Response.Write(Session("percent"))
Response.End()
End If
And finally you need to read the percentage with JavaScript using timer. This is best done with jQuery as pure JavaScript AJAX is a big headache. After you add reference to the jQuery library, have such code:
var timer = window.setTimeout(CheckPercentage, 100);
function CheckPercentage() {
$.get("?getpercent=1", function(data) {
timer = window.setTimeout(CheckPercentage, 100);
var percentage = parseInt(data, 10);
if (isNaN(percentage)) {
$("#remain").text("Invalid response: " + data);
}
else {
$("#remain").text(percentage + "%");
if (percentage >= 100) {
//done!
window.clearTimeout(timer);
}
}
});
}
Holding respond untill your complete processing is done is not a viable option, just imagine 30 people accessing the same page, you will have 30 persistent connections to the server for a long time, especially with IIS, i am sure its not a viable option, it might work well in your development environment but when you move production and more people start accessing page your server might go down.
i wish you look into the following
Do the processing on the background on the server and do not hold the response for a long time
Try to write a windows service which resides on the server and takes care of your mass mailing
if you still insist you do it on the web, try sending one email at a time using ajax, for every ajax request send an email/two
and in your above example without response.flush the browser will also not get the % information.
Well, you don't.
Except for simple effects like printing dots or a sequence of images it won't work safely, and even then buffering could interfere.
My approach would be to have an area which you update using an ajax request every second to a script which reads a log file or emails sent count file or such an entry in the database which is created by the mass mailing process. The mass mailing process would be initiated by ajax as well.
ASP will not write anything to the page until it's fully done processing (unless you do a flush)
Response.Buffer=true
write something
response.flush
write something else
etc
(see example here: http://www.w3schools.com/asp/met_flush.asp)
A better way to do this is to use ajax.
Example here:
http://jquery-howto.blogspot.com/2009/04/display-loading-gif-image-while-loading.html
I didn't like ajax at first, but I love it now.

ajax sending request twice

Example URL: http://twitter.realgamingreview.com/index.php
Edit: forgot to mention: use the test sign in: test/test for username/password.
I am attempting to do a simple AJAX request to retrieve some data from a database. The target file, serverTime.php, seems to be working perfectly; it inserts the desired data and returns the desired responseText.
However, the request seems to be firing twice. This is clear when I step through the JavaScript using Firebug. This causes the page to 'reset' (not exactly sure), such that my cursor loses focus from its current textbox, which is a new problem. The URL also says, "localhost/twitter/index.php?message=", even if my message is not actually empty. I want to fix this fairly minor problem before something major comes of it.
The JavaScript is below. ajaxRequest is my XMLHTTPRequest object. Any help is appreciated!
//Create a function that will receive data sent form the server
ajaxRequest.onreadystatechange = function(){
if (ajaxRequest.readyState == 4){
document.getElementById('output').innerHTML = ajaxRequest.responseText;
}
}
// build query string
var message = document.myForm.message.value;
var queryString = "message=" + message;
//send AJAX request
ajaxRequest.open("GET", "serverTime.php" + "?" + queryString, true);
ajaxRequest.send(null);
Thanks,
Paragon
I've seen this many times, and for me it's always been firebug. Try TURNING OFF firebug and submit the request again. Use fiddler or some other means to verify the request only executed once.
When I write AJAX functions in Javascript, I usually keep around a state variable that prevents a new request from being dispatched while one is currently in progress. If you just want to ignore requests that are made before another one finishes, you can do something like this:
Initialize inProgress to false.
Set inProgress to true right before calling ajaxRequest.send(). Do not call ajaxRequest.send() unless inProgress is false.
ajaxRequest.onreadystatechange() sets inProgress to false when the state is 4.
In some cases, however, you'd like to queue the actions. If this is the case, then you can't just ignore the request to ajaxRequest.send() when inProgress is true. Here's what I recommend for these cases:
Initialize ajaxQueue to an empty global array.
Before calling ajaxRequest.send(), push the request onto ajaxQueue.
In ajaxRequest.onreadystatechange() when the state is 4, pop the array to remove the request just services. Then, if ajaxQueue is not empty (array.size > 0), pop again and call send() on the object returned.
My issue was completely unrelated to AJAX. Instead, it was a simple (but obscure) issue where with two textboxes in my form, I was able to hit enter and not have the page reload, but with only one, the page would reload for some reason.
I have since changed my event system such that I am not relying on something so unreliable (now using jQuery to listen for the Enter key being pressed for specific textboxes).
Thanks to those of you who took the time to answer my misinformed question.

Categories