Safari Not Updating UI During Form Submission - javascript

I've got a JavaScript function that submits a form.
The first step of my function is to disable it (to prevent multiple clicks) and apply a class that better illustrates that it's disabled. I also change the text to 'Please Wait...'
The next step is to validate my form. If validation fails, revert the changes in the first step, to return the button to its normal state.
If validation passes, submit the form.
This all essentially happens in the same process.
What I find is happening, is that in Safari, the first stage of the process (the button styles) is all but ignored. Upon further digging, I realised that it is working but the UI isn't redrawing until after the process completes. The problem here is that the completion of the process is a redirect away from the page, so the user never gets to see 'Please wait...'
Then I explored why Safari isn't redrawing the UI and I discovered a number of fixes for this, one such example is below:
// Aims to trigger the redraw by 'resetting' it
elem.style.display='none';
elem.offsetHeight;
elem.style.display='';
Another one I tried was deliberately hiding and showing the element before/after the update utilising Prototype (which is the primary JavaScript library on the system):
elem.hide();
elem.addClassName('disabledBtn');
elem.disable();
elem.update('Please Wait');
elem.show();
Another was to create a 'redraw' method to force a redraw.
Element.addMethods({
redraw: function(element){
element = $(element);
var n = document.createTextNode(' ');
element.appendChild(n);
(function(){n.parentNode.removeChild(n)}).defer();
return element;
}
});
...
elem.addClassName('disabledBtn');
elem.disable();
elem.update('Please Wait');
elem.redraw();
None of these items will work. The process will not update the UI until after the completion, and the user has redirected away. For reference, this is a pretty intensive form with a good few seconds of processing required during its submission, so this is a UX nightmare.
Has anybody else come across this situation?

I've figured this out.
As this is technically a workaround, rather than a solution to the problem, I'd still be open to other answers that may solve the issue outright.
I thought about this 'process' terminology, and how I could effectively end the process - thereby applying the styles, and start another one to submit the form.
The way I figured this out was to take the final stage of my code (the form submission) and push it into an asynchronous process. This way, the styling and validation 'process' will complete, with the style changes taking effect immediately, and the form submission will happen at some point after this.
I managed this asynchronous process with setTimeout()
elem.observe('click', function(e) {
// [Disabled styles]
// [Form Validity]
if (!valid) {
// [Reverse Button Disabling]
} else {
setTimeout(function(){ $('myform').submit(); }, 0);
}
});

Have you tried stopping the event first (in case your button is an actual type="submit")? i.e.
elem.observe('click', function(e) {
e.stop(); // prevent the default actions
// [Disabled styles]
// [Form Validity]
if (!valid) {
// [Reverse Button Disabling]
} else {
$('myform').submit();
}
});

Related

How to indicate that a function is executing which re-renders the DOM?

In Angular I have loaded a page. After I press a button "Change" a function is called
ng-click = "changeFunction()"
in which the content of the page is re-evaluated and changes (the change is mostly in {{textVariables}} and images of the page).
If the content of the page being changed is less, this switch is fast enough to not be an issue. However if a lot of the content is being changed, the button appears pressed for an extended period of time, which gives the appearance that something in the page has broken (even though it has not, it is just taking time to re-evaluate the content).
How do I then modify my changeFunction() in the angular controller to mark a flag true when it starts changing and false when it finishes changing, so that I can use the flag to perhaps show the user something is happening?
To be clear, I am just asking for the javascript part of the code, the UI element I can design.
This should be a straightforward addition:
changeFunction() {
if (!this.saving) {
this.saving = true;
}
// Your code here;
// This is the last bit of the method:
this.saving = false;
}
Then elsewhere in the controller (or the template) you can check for this.saving or (if you're using 'vm' in the template) vm.saving.

Form submission blocking issues

I'm new here in terms of asking questions, but I have read many articles/questions/answers for quite some time now. My question is about part of a code that got me stuck for some time now.
So in my project I've got a registration form that has an JS validation and server side validation. Now what I wanted to do is disable form submitting before the JS validation is ok and I've set some conditions for it to be like that. Now the problem occured when those conditions were met. I used this line to stop form from submiting:
$('.memberReg').on('submit',function(){return false;});
In a situation like this for instance:
if(response.okText == 'SUCCESS' && response.warning == null )
{
$('label[for="email"]').addClass("success");
$('label[for="email"]').append("<span> is not yet registered!</span>");
console.log(result);
}else
{
$('label[for="email"]').addClass("error");
$('label[for="email"]').append("<span> is already taken!</span>");
$('.memberReg').on('submit',function(){return false;});
}
What happens here is that I do block the form from submiting, but it is blocked entirely, even when the other conditions are met. In this example even with correct email you cannot submit anymore.
I have tried using a variable with true-false statements that would make a validForm() function submit the form, but the function starts looping and it is still not enabling the form.
I also tried using return true for the form submit in the valid email part, still the same effect.
Anyone knows how to block it only on a certain condition without blocking it entirely so that the user has to refresh if he wants to send?
I believe I figured it out, after a few test runs it works smoothly, so I will post it in case someone else might have the same problem.
So at start I used:
$('.memberReg').on('submit',function(){return false;});
Which was overwriting the submit handler as one of the good people told me in one of his answers. So I tried changing my approach to the way I want to implement it and used:
$( ".memeberReg" ).submit(function( event ) {
if ( condition ) {
//successfulValidationCode
return;
}
//errorCode
event.preventDefault();
})
Under conditions I am checking the variables that I set in my field validations and in case of a bad input i use event.preventDefault(); to block the form again.
The problem is that you're overwriting the submit handler, and once it is overwritten, it is gone until the page is reloaded. I would question this approach entirely to be honest; you shouldn't have to overwrite the submit handler to prevent the form being submitted.
By the way, you're using JavaScript validation, not AJAX validation. AJAX is the process of sending a request to the server, and potentially receiving a result, without refreshing the page

JS - Pause custom alert()

I've edited the default alert() function like this:
window.alert = function(str){
//custom alert
}
Essentially, the new function will show an HTML <div> modal.
Backstory:
I want to answer to this question because I am having a problem. The alert is hidden and will show when the custom alert function is called. So the custom alert is basically showing the element and changing it's text. Therefore, when I have multiple alert() calls, only the last message is displayed! :(
But, unlike the default alert box. It of course won't pause the webpage until the alert goes away like the default alert() function.
Is it possible to imitate this "pause the webpage" behavior?
Also, is there another way other then using setTimeout() to check if isCustomAlertOpen == true to delay another custom alert from triggering until the current one is dismissed?
Edit:
Is there a way to queue up the custom alerts?
I don't mind jQuery, but I thought it might be overpowered here.
My question title is bad. Can someone think of a better title for me please?
There is no way to block the execution because JavaScript is asynchronous (except obviously 3 modal functions and XmlHttpRequest).
For the same reason, you can't wait for a previous alert to be closed, but you can use events to create a stack of alerts using this pattern:
window.alert = (function() {
var stack = [];
var showNextAlert = function() {
var div = document.createElement("div");
/* Here, configure the div, show the string from stack[0] and add it to the document ... */
var okButton = /* ... */;
okButton.addEventListener("click", function() {
div.parentNode.removeChild(div);
stack = stack.slice(1);
if(stack.length > 0) {
showNextAlert();
}
});
}
return function(msg) {
stack.push(msg);
if(stack.length == 1) {
// Show it immediately if the stack is empty
showNextAlert();
}
};
})();
You should also use another name for this function instead of changing native properties (here window.alert).
Is it possible to imitate this "pause the webpage" behavior?
The answer to this is no. There are ways to block the ui (sync ajax call, long loop etc). But you wouldn't be able to stop these when the user has click the ok button.
A better approach would be to restructure the code so that it didn't run synchronously. Ie you wouldn't need to block the ui while waiting for the user.
Also, is there another way other then using setTimeout() to check if isCustomAlertOpen == true to delay another custom alert from triggering until the current one is dismissed?
One way to do this is: instead of setting a flag in one place and checking it repeatedly in another. You can use the concept of events. One part of code is waiting for an event to be triggered and another part triggers it. There is a library in jQuery which can do this for you or you could read up on it and write your own.

Is it possible to refresh a form only?

I have a form that when is submited it posts to a div. Ok, so I found the issue that i was getting double submissions, so i tried to apply some jquery plugins i found, but they were useless because if you double clicked fast enough I still got a double submission. From those I found i saw the best way to prevent it was with
if (this.beenSubmitted) return false;
else
this.beenSubmitted = true;
but then, I noticed that if the form needed to be sent again, the user would have to refresh the page in order to send it. In my case, I want them to be able to send again after is sent, (Im not contradicting myself, because it would be diferent content). To explain it better, this form post ideas. If you want to post 2 diferent ideas you would have to refresht he page to post. Preventing double submission would help from submitting the same idea twice if you clicked fast enough. So, what I did is that I added this "5000":
if (this.beenSubmitted) return false, 5000;
else
this.beenSubmitted = true;
So, now it refreshed my page. But im a little picky, lol. So I find it annoying that the whole page has to refresh. What if your typing and then it refreshes. I can always lower the 5000 I know, but I still find it annoying in case you start to browse the website or to zoom in, you end up refreshed.
So, my question is, is there any way to just refresh the form? or a better way to prevent double submission that actually works for this case (that ur able to submit after a few secs) ?
this is script:
<script type="text/javascript">
$(document).ready(function(){
$("form#myform").submit(function() {
var addcontent = jQuery('#addcontent').attr('value');
if ( addcontent.replace(/\s/g,"") == "" ) return false;
if (this.beenSubmitted) return false,5000;
else
this.beenSubmitted = true;
$.ajax({
type: "POST",
url: "post.php",
data:"addcontent="+ addcontent,
success: function(){blah blah blah, ton sof code here including pagintion here, insert into a div here also, if u need this let me know.
});
</script>
Most of that I did it from asking questinos here. My Jquery and Ajax knowledge isnt the best one.
THanks for the help =}
Rate limiting to prevent malicious behavior in ExpressJS
The above link has something about putting a timer on the submit button so that you can't click it again within 3 seconds.
<script>
var submitTimer = new Collate(3000);
</script>
<form action="post" onsubmit="return submitTimer.idle();">
why don't u use the this.beenSubmitted = true approach and combine it with a timeout? for example after 5000ms u execute the timeout and set this.beenSubmitted to false.
The statement:
return false, 5000;
will always return 5000, the use of false is redundant and pointless.
To reset a form without reloading the page (which won't necessarily reset the form in some browsers), use a reset button or call the form's reset method. You can use an onreset listener to update the beenSubmitted property if the form is reset.
Multiple submission of a form has been an issue since forms were invented, it's usually dealt with at the server (if two identical requests are received, ignore the second).
Using script at the client is unreliable since you don't know what the server is doing and you have to guess whether or not the form needs to be resubmitted.

ASP.NET/jQuery Post-Back, but not when using browser's "Back" button

I'm working on an ASP.NET Web Project with some AJAX magic. As my GridView's data needs up to 15 seconds to be gathered, I send the page to the client and fire an asynchronous update of an UpdatePanel via jQuery/JScript (see below).
This works well, so far. Now I'd like to skip this step when the user navigates to the next page (e.g. record detail view) and comes back via the "Back" button. Is there a way to get his, and what's the most elegant one?
This one does not work (hasDonePostBack's value isn't kept by the browser):
var hasDonePostBack = false;
function fRefreshAsyncOnce(id, param) {
$(document).ready(function() {
if (!hasDonePostBack) {
__doPostBack(id, param);
hasDonePostBack = true;
}
});
}
Any help would be great!
The reason why this is important: Regetting the data takes another 15 seconds. Moreover, the grid is working with controls and more client script (e.g. checkboxes that can be checked, CSS classes that are toggled, etc.), and all this should be the same after returning.
Cheers,
Matthias
You may want to look at the history point feature; you may be able to take advantage of that for this feature: http://msdn.microsoft.com/en-us/library/cc488548.aspx
However, that is the nature of the beast when triggering client-side operations... the other option is allowing the user to cancel the postback (or try to interpret a way to cancel it yourself) using this technique: http://msdn.microsoft.com/en-us/library/bb398789.aspx

Categories

Resources