I've found variants of this problem on Stack Overflow but nothing my matches my specific circumstance. Hopefully someone has some insight.
Right now I'm working on a web application where there is a button (technically an anchor tag) that spawns a list of items when pressed. The issue is, if the user presses this button rapidly twice in a row, the list will be spawned twice-- the button is meant to clear the list before spawning it to prevent duplication, but something about the way the scripts interact is causing this bug. The button spawns the list by making an ajax call to a server.
Now, I've tried fixing this bug by flipping a boolean value to 1 when the button is pressed, and making the button do nothing until it is 0 again. This seems not to work regardless of where in the code I set the value to 0 again: I've tried putting it at the end of the ajaxGet function, as well as after page load, but neither solution works.
Ideally, I would like a way for the button to become enabled as soon as the page is completely finished loading and rendering. Ultimately, what's needed is a way of preventing the user from pressing the button twice in a row. I've considered using a timer for this, but I'd prefer not to have to resort to that.
Any ideas? Let me know if you would like code snippets.
===========================================
EDIT: Thanks everyone for your answers! I used a variant of Fibrewire's answer to solve the problem, and it works great. At the beginning of the method that the button calls, I put the following code:
if (actionsDisabled == 1) {
return;
}//if
else {
actionsDisabled = 1;
setTimeout("actionsDisabled=0;", 1000);
}//else
Where actionsDisabled is a global boolean. It might not be as airtight as it could be (in particular, you'd hit a problem if the list took more than a second to load), but it's elegant and functional, and has the added bonus of reducing server requests (if traffic ever became a problem, you could restrict calls to once every 5 or 10 seconds or whatever). Thanks again!
you can disable the button after the first click
Disabling the button after once click
and if you need the user to be able to click the button again in the future you can use the setTimeout() method to re enable it after a brief pause
http://www.w3schools.com/jsref/met_win_settimeout.asp
Related
I don't know if this is the effects of an update panel or what, but I basically have a drop down list that allows a user to select an item as a filter. When the item is selected it should bring back only one item into a grid view. That is this specific filter will at most bring back the record you are looking for. This works fine if the user clicks an "apply" link to apply the filter. Behind the apply link is some server-side code (C# within an ASP.NET Web Forms application).
We had a request by a user with something to the effect of:
"Why do I have to click the apply button if I make a selection in this
one drop down filter...it should simply get that one record I am
searching for. This helps me because I don't have to click the
"Apply" button."
I agreed with him and thought what is the easiest way to do this...I thought: Simple, I will have an on change event handler of the drop down such that when a selection is made I'll trigger a click event. Something to this effect:
$("#MainContent_ddlCompany").on("change", function() {
var companyId = $("#MainContent_ddlCompany").val();
$("#MainContent_hdnCompanyValue").val(companyId);
$("#<%=ddlCompany.ClientID %>").trigger("chosen:updated");
if (companyId.length > 0) {
$(".apply").click();
$(".apply").removeClass("applyButton");
$(".apply").addClass("resetButton");
} else {
//cleared selection of a company
$(".apply").removeClass("resetButton");
$(".apply").addClass("applyButton");
}
});
At first this didn't work, and I couldn't tell why, but then after some serious googling I changed this line:
$(".apply").click();
To this:
$('.apply')[0].click();
That worked great...so I decided to test it some more. As I kept selecting one filter value after another I noticed the page started to slow down. In fact by the 6th or 7th time it was pretty unusable. I don't know why it's happening, but I suspect again it has to do with the fact that this linkbutton with the class name .apply is inside an update panel.
But still I thought to myself, it was inside of an update panel before I changed my jQuery code to simulate the click event. So why does the page slow down and drag with this little piece of code? Is calling the event from jQuery code rendering something else in the HTML that could be causing this?
If I change my code back and force the user to click the apply button then we are back to a good normal speed. Why is it if I tell jQuery to simulate clicking the button my page slow down? It's doing the same thing, the simulation of the click of this link button is calling its server-side code method whether the user clicks it or I have jQuery click it.
For now I'm at a loss as to why this is happening because this button is in an update panel in either case, yet when I have jQuery click it via $('.apply')[0].click(); the page slows down after several attempts. Yet when I have the user simply click this button (without the jQuery click event) then it works fine?
What am I missing here?
Ugh, well, I found my issue. Because I was using updatepanels I had to wrap my jQuery code to include an add_endRequest. That is, you have something to the effect of:
$(document).ready(function() {
//Some initial event/triggers
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function () {
//Copy of some initial event/triggers
});
});
Why do I use the endRequest you ask? Well, because updatepanels basically throw away all your events after an asynchronous postback because the HTML at that point (after an update) is rendered again and at that point all events associated with any control inside an update panel are wiped away. At this point of course document.ready() does not run, so I have to resubscribe to these events inside of endRequest. Enter my issue...
I had a huge brain fart where I basically took everything, literally everything inside document ready and copied it into endRequest. In fact, if I remember correctly, I read articles which stated
Whatever you have in document ready simply copy paste into endRequest
That's fine, but you have to be careful here. I was throwing in events that were not wrapped around inside of an updatepanel into endRequest. The result is disastrous...at least for me.
These events would be attached then multiple times..or based on the number of asynchronous postbacks made. In my case, as I was testing I mentioned after the 6th or 7th time performance starts degrading. Well, by that time my controls were being attached that many times to events. For instance, my .apply button along with my dropdownlist were both outside of my updatepanel. But my jQuery code was attaching the change event of my dropdownlist in both document ready and endRequest.
The result is initially it's pretty fast, because it's only in document ready. But as I make asynchronous postbacks these events are being attached every time. For n tests I would have n attached events...in my case the test of 7 yields 7 on change event handlers!
Case in point, do not place any event handlers such as jQuery's on() event for any controls that are NOT inside an update panel. Otherwise you will run into what I ran into which was poor performance as events are happening.
First of all, apologies if this question was answered before.
I'm writing a code in JS to read an Excel File, get the value of the first cell in the column, search for it (it's an ISBN code, which I'm searching with the Google Books API) and get other relevant info, made available through the search (like Title, Subtitle and Author), then proceed to the next line and repeat the process.
My problem is writing the new data back in the Excel File. The code is writing all info in the last used row in the file. While using window.alert to flag the code, I noticed that when the alert was in a for loop, right before the search was initiated, the new data was inserted just fine, but if I tried to use a pause (like a timer function or a while loop to consume time) it didn't help at all.
What I want to know is why that behavior might be happening and, if possible, of course, a possible solution for my problem, since having to use alert as a pause isn't exactly the most interesting solution.
Thanks in advance
Alert will always stop all execution of code, except for web workers. Therefore, If you need to continue execution, use a web worker. Have a look at this for reference (the note part covers this topic partially)
When browsers show a native modal interaction widget, such as an alert, it transitions into a state that waits for the response. In this state, it is allowed to redraw the page and process certain low level events. Here's the code from Mozilla Firefox that alert() and confirm() use:
http://mxr.mozilla.org/mozilla-central/source/toolkit/components/prompts/src/nsPrompter.js#434
This openRemotePrompt function doesn't return until the user clicks "OK" on the alert. However browser behaves differently while the alert is open. A loop repeatedly calls thread.processNextEvent to do certain kinds of work until the dialog is closed. (It doesn't run the application's JavaScript code, since that's meant to be single-threaded.)
When you use a pure JavaScript busy wait, for example, by looping until a certain wall time, the browser doesn't take these measures to keep things moving. Most noticeably, the UI won't redraw while the JavaScript code is looping.
I am supporting an e-commerce app, which pretty much makes and submits orders.
A user found that if they submit their order, and press back really quickly, they can cause an error condition.
I want to prevent this. When the user clicks submit, I want to bind some kind of event to the browser's back button that instead will redirect them to the Index page. However, after about two hours of Googling (including a few StackOverflow topics), I have not found any clear way of influencing the behavior of the back button.
I briefly attempted to use history.pushState(), but as the HTML 5 documentation mentions, that will not cause a redirect; it merely alters the displayed URL/state.
Similarly, the history.onpopstate event appears unhelpful, because it occurs whenever a state is removed from the history listing; I'm looking for an event that occurs whenever the history listing is traversed backwards.
Question: Does an event for the browser's back button, or at least a way to prevent this particular stupid user trick exist?
You can't listen to the browser back button because it's outside of your reach (it's not part of the DOM).
What you can do is fix the previous page so that it detects if you've used the back button.
Without more information I can't give you any tips on how to achieve that.
Also, an error condition is not necessarily a bad thing. Just make sure it's clear what is happening: the error message should make sense.
Wrong answer...
Instead listen to window.onBeforeUnload and ask the user if he knows what he is doing. Return false if not. This is usually done via a confirm dialogue
I have a webpage that use $(document).ready() to build the interface. Then the user can go to a child page, and to go back to the original page he can press the browser's "previous" button or a "Return" button in the page which triggers a history.back();. Back on the original page, $(document).ready() is not triggered so the page is missing information.
Is there a way to trigger it automatically like if it was a "real load"?
edit
placing an alert in it, the alert is popped but stuff is missing in my interface like if some part of the ready event is missing. Investigating...
edit 2
hahahahaha in document.ready I click some checkbox which are supposed to be unchecked. When I "back" on this page, they are checked so they become unchecked because I reclick them.
Sorry, this is completely my bad :(
A quick solution to this problem, use "onpageshow" instead.
window.onpageshow = function(event) {
//do something
};
If the user uses the Back button to navigate and you require a full reload of the page, you can set the NO-CACHE policy of the page.
This way the browser is forced to reload the page from the server, even using the Back button.
1.) put scripts at the bottom of your page.
2.) execute plugins and whatnot in your last script tag(s).
3.) Do not use onDomReady implementations at all, it's redundant.
People are so accustomed to onload or ondomready, they overlook the fact that putting your scripts at the bottom of a page does virtually the same thing without the need to poll and see if your html is available.
Furthermore, it's also good practise as your scripts do not block html/css rendering either.
Not depending on onDomReady or onLoad implementations solves a lot of issues.
Very interesting question. You might need to re-trigger the event/function when the page gets focus, or something similar. you might also need to keep a flag variable to track whether an 'event re-triggering' is in order.
I am working on a site that has loads of legacy Javascript and jQuery includes and there is no documentation to show what is happening when.
I have a specific problem to fix and I cannot find the relevant code that is being executed when a button is clicked. To save me from trawling through (and making sense of) hundreds of lines of legacy script, is there a feature, possibly in Firebug, that will identify what script is being executed when I click on a button?
I believe there is a feature in Firebug's console window called Profile. Click profile, click the button, then click profile again. It should give you what all functions were called in that time. Be warned that if this code includes jQuery, you might get a huge long list of functions because jQuery uses tons in its code. Unfortunately, the profiler will also show anonymous functions, which can really be a pain.
Otherwise, do a search in the code for the button's class or ID and go through them. If you have an id of fancy then you might do a search for #fancy in your code and attempt to find it. That may lead you in a general direction, at least.
You can click Firebug's "Break on next" button (in the Script tab; it looks like a pause button), then push the button that you want to debug.
The next time any JavaScript code executes, Firebug will break into the debugger and show you that line of code.
The break button didn't work for me. Instead I did edit the onclick attribute with FireBug and prepended it with "debugger;" ... then you'll break right there once you click :)
None of the above answers worked for me. I am trying to use Firebug to figure out how a feature on a page is working for a site I have no control over. Here is what worked for me.
First, got the id of the element I am clicking on from the page source, and then get a temporary reference to it by creating a watch (under the script tab):
tmp=document.getElementById("idOfElement")
Next, I assigned the current onclick value to another temporary variable.
oldfunc=tmp.onclick
Next, I defined a new onclick function. Initially I tried putting debugger; as the first thing in the function, but this does not work! So instead, I created an alert:
tmp.onclick = function() { alert("Ok"); oldfunc() }
Now, as soon as I click on the button the alert comes up, at which point I then click the "Break on next" button as outlined in another answer to this question. Then I dismiss the alert and immediately I am in the debugger at the correct place.
In my case, the "Break on next" button did not work by itself, because there are a lot of other events, just mousing over the page was causing the breakpoint to be hit, preventing me from ever clicking the button.
In Firebug you can set a breakpoint in some JS and then you get a stack which will let you know the current function call stack. So if you set the breakpoint in function used by several handlers then you can use this to discover exactly which handler you are in.
This probably won't work if you are dealing with AJAX callbacks and the like though.