I have following jQuery code to prevent double clicking a button. It works fine. I am using Page_ClientValidate() to ensure that the double click is prevented only if the page is valid. [If there are validation errors the flag should not be set as there is no postback to server started]
Is there a better method to prevent the second click on the button before the page loads back?
Can we set the flag isOperationInProgress = yesIndicator only if the page is causing a postback to server? Is there a suitable event for it that will be called before the user can click on the button for the second time?
Note: I am looking for a solution that won't require any new API
Note: This question is not a duplicate. Here I am trying to avoid the use of Page_ClientValidate(). Also I am looking for an event where I can move the code so that I need not use Page_ClientValidate()
Note: No ajax involved in my scenario. The ASP.Net form will be submitted to server synchronously. The button click event in javascript is only for preventing double click. The form submission is synchronous using ASP.Net.
Present Code
$(document).ready(function () {
var noIndicator = 'No';
var yesIndicator = 'Yes';
var isOperationInProgress = 'No';
$('.applicationButton').click(function (e) {
// Prevent button from double click
var isPageValid = Page_ClientValidate();
if (isPageValid) {
if (isOperationInProgress == noIndicator) {
isOperationInProgress = yesIndicator;
} else {
e.preventDefault();
}
}
});
});
References:
Validator causes improper behavior for double click check
Whether to use Page_IsValid or Page_ClientValidate() (for Client Side Events)
Note by #Peter Ivan in the above references:
calling Page_ClientValidate() repeatedly may cause the page to be too obtrusive (multiple alerts etc.).
I found this solution that is simple and worked for me:
<form ...>
<input ...>
<button ... onclick="this.disabled=true;this.value='Submitting...'; this.form.submit();">
</form>
This solution was found in:
Original solution
JS provides an easy solution by using the event properties:
$('selector').click(function(event) {
if(!event.detail || event.detail == 1){//activate on first click only to avoid hiding again on multiple clicks
// code here. // It will execute only once on multiple clicks
}
});
disable the button on click, enable it after the operation completes
$(document).ready(function () {
$("#btn").on("click", function() {
$(this).attr("disabled", "disabled");
doWork(); //this method contains your logic
});
});
function doWork() {
alert("doing work");
//actually this function will do something and when processing is done the button is enabled by removing the 'disabled' attribute
//I use setTimeout so you can see the button can only be clicked once, and can't be clicked again while work is being done
setTimeout('$("#btn").removeAttr("disabled")', 1500);
}
working example
I modified the solution by #Kalyani and so far it's been working beautifully!
$('selector').click(function(event) {
if(!event.detail || event.detail == 1){ return true; }
else { return false; }
});
Disable pointer events in the first line of your callback, and then resume them on the last line.
element.on('click', function() {
element.css('pointer-events', 'none');
//do all of your stuff
element.css('pointer-events', 'auto');
};
After hours of searching i fixed it in this way:
old_timestamp = null;
$('#productivity_table').on('click', function(event) {
// code executed at first load
// not working if you press too many clicks, it waits 1 second
if(old_timestamp == null || old_timestamp + 1000 < event.timeStamp)
{
// write the code / slide / fade / whatever
old_timestamp = event.timeStamp;
}
});
you can use jQuery's [one][1] :
.one( events [, data ], handler ) Returns: jQuery
Description: Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
see examples:
using jQuery: https://codepen.io/loicjaouen/pen/RwweLVx
// add an even listener that will run only once
$("#click_here_button").one("click", once_callback);
using count,
clickcount++;
if (clickcount == 1) {}
After coming back again clickcount set to zero.
May be this will help and give the desired functionality :
$('#disable').on('click', function(){
$('#disable').attr("disabled", true);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="disable">Disable Me!</button>
<p>Hello</p>
We can use on and off click for preventing Multiple clicks. i tried it to my application and it's working as expected.
$(document).ready(function () {
$("#disable").on('click', function () {
$(this).off('click');
// enter code here
});
})
This should work for you:
$(document).ready(function () {
$('.applicationButton').click(function (e) {
var btn = $(this),
isPageValid = Page_ClientValidate(); // cache state of page validation
if (!isPageValid) {
// page isn't valid, block form submission
e.preventDefault();
}
// disable the button only if the page is valid.
// when the postback returns, the button will be re-enabled by default
btn.prop('disabled', isPageValid);
return isPageValid;
});
});
Please note that you should also take steps server-side to prevent double-posts as not every visitor to your site will be polite enough to visit it with a browser (let alone a JavaScript-enabled browser).
The absolute best way I've found is to immediately disable the button when clicked:
$('#myButton').click(function() {
$('#myButton').prop('disabled', true);
});
And re-enable it when needed, for example:
validation failed
error while processing the form data by the server, then after an error response using jQuery
Another way to avoid a quick double-click is to use the native JavaScript function ondblclick, but in this case it doesn't work if the submit form works through jQuery.
One way you do this is set a counter and if number exceeds the certain number return false.
easy as this.
var mybutton_counter=0;
$("#mybutton").on('click', function(e){
if (mybutton_counter>0){return false;} //you can set the number to any
//your call
mybutton_counter++; //incremental
});
make sure, if statement is on top of your call.
If you are doing a full round-trip post-back, you can just make the button disappear. If there are validation errors, the button will be visible again upon reload of the page.
First set add a style to your button:
<h:commandButton id="SaveBtn" value="Save"
styleClass="hideOnClick"
actionListener="#{someBean.saveAction()}"/>
Then make it hide when clicked.
$(document).ready(function() {
$(".hideOnClick").click(function(e) {
$(e.toElement).hide();
});
});
Just copy paste this code in your script and edit #button1 with your button id and it will resolve your issue.
<script type="text/javascript">
$(document).ready(function(){
$("#button1").submit(function() {
$(this).submit(function() {
return false;
});
return true;
});
});
</script
Plain JavaScript:
Set an attribute to the element being interacted
Remove the attribute after a timeout
If the element has the attribute, do nothing
const throttleInput = document.querySelector('button');
throttleInput.onclick = function() {
if (!throttleInput.hasAttribute('data-prevent-double-click')) {
throttleInput.setAttribute('data-prevent-double-click', true);
throttleInput.setAttribute('disabled', true);
document.body.append("Foo!");
}
setTimeout(function() {
throttleInput.removeAttribute('disabled');
throttleInput.removeAttribute('data-prevent-double-click');
}, 3000);
}
<button>Click to add "Foo"!</button>
We also set the button to .disabled=true. I added the HTML Command input with type hidden to identify if the transaction has been added by the Computer Server to the Database.
Example HTML and PHP Commands:
<button onclick="myAddFunction(<?php echo $value['patient_id'];?>)" id="addButtonId">ADD</button>
<input type="hidden" id="hasPatientInListParam" value="<?php echo $hasPatientInListParamValue;?>">
Example Javascript Command:
function myAddFunction(patientId) {
document.getElementById("addButtonId").disabled=true;
var hasPatientInList = document.getElementById("hasPatientInListParam").value;
if (hasPatientInList) {
alert("Only one (1) patient in each List.");
return;
}
window.location.href = "webAddress/addTransaction/"+patientId; //reloads page
}
After reloading the page, the computer auto-sets the button to .disabled=false. At present, these actions prevent the multiple clicks problem in our case.
I hope these help you too.
Thank you.
One way I found that works is using bootstrap css to display a modal window with a spinner on it. This way nothing in the background can be clicked. Just need to make sure that you hide the modal window again after your long process completes.
so I found a simple solution, hope this helps.
all I had to do was create a counter = 0, and make the function that runs when clicked only runnable if the counter is = 0, when someone clicks the function the first line in the function sets counter = 1 and this will prevent the user from running the function multiple times when the function is done the last line of the code inside the function sets counter to 0 again
you could use a structure like this, it will execute just once:
document.getElementById('buttonID').addEventListener('click', () => {
...Do things...
},{once:true});
I'm trying to use the placeholder="xxx" attribute in my web application, and I don't want to have a special visual for IE9. Can people throw out some good suggestions for achieving this functionality in IE9?
I've found a couple links on here but none of the suggested scripts were sufficient... and the answers were from mid-2011, so I figured maybe there is a better solution out there. Perhaps with a widely-adopted jQuery plugin? I do not want to use anything that requires intrusive code such as requiring a certain css class or something.
Thanks.
EDIT - I also need this to work for password input fields.
// the below snippet should work, but isn't.
$(document).ready(function() {
initPlaceholders()();
}
function initPlaceholders() {
$.support.placeholder = false;
var test = document.createElement('input');
if ('placeholder' in test) {
$.support.placeholder = true;
return function() { }
} else {
return function() {
$(function() {
var active = document.activeElement;
$('form').delegate(':text, :password', 'focus', function() {
var _placeholder = $(this).attr('placeholder'),
_val = $(this).val();
if (_placeholder != '' && _val == _placeholder) {
$(this).val('').removeClass('hasPlaceholder');
}
}).delegate(':text, :password', 'blur', function() {
var _placeholder = $(this).attr('placeholder'),
_val = $(this).val();
if (_placeholder != '' && (_val == '' || _val == _placeholder)) {
$(this).val(_placeholder).addClass('hasPlaceholder');
}
}).submit(function() {
$(this).find('.hasPlaceholder').each(function() { $(this).val(''); });
});
$(':text, :password').blur();
$(active).focus();
});
}
}
}
We just researched the same thing. We decided on reusing this gist, by Aaron McCall, after making some minor changes. The main advantage is that it's simple, easy to understand code:
Remove the kernel and setup_placeholders parts. Just call it immediately in an anonymous function.
Add var before test.
For browsers that support placeholder, it simply falls back to that. It also handles new input elements (note the use of delegate) in existing forms. But does not handle dynamic new form elements. It could probably be modified to do so with jQuery.on.
If you don't like this one, you can use one of the ones here. However, some of them are overcomplicated, or have questionable design decisions like setTimeout for detecting new elements.
Note that it needs to use two pairs of parens, since you're calling an anonymous function, then calling the returned function (this could be factored out differently):
(function () {
// ...
})()();
I wrote a jquery plugin a while back that adds the placeholder support to any browser that does not support it and does nothing in those that do.
Placeholder Plugin
Here's a jQuery plugin that works with password fields as well. It's not as tiny as the code suggested by Matthew but it has a few more fixes in it. I've used this successfully together with H5Validate as well.
http://webcloud.se/code/jQuery-Placeholder/
I made this fiddle
http://jsfiddle.net/nAb6N/10/
As you can see I have 2 animators , a element and body class,
I am adding class to body after the first click on a element but once I click on body is not closing it. If I define animators as
var animators = $$('#opendiv,body');
it works ok except that I do not want the div to open on body click. I need it to close on body click.
Any help is appreciated.
Thank you!
Right. Seems as if you really require an outerClick pattern to close. Here's the one that is most notably used within mootools devs, allowing you to create a custom event, based on click:
Element.Events.outerClick = {
base : 'click',
condition : function(event){
event.stopPropagation();
return false;
},
onAdd : function(fn){
this.getDocument().addEvent('click', fn);
},
onRemove : function(fn){
this.getDocument().removeEvent('click', fn);
}
};
The way it works is: it is based on a normal click. upon adding, it adds the callback as a click event on the document. when a click happens within the element itself,it stops bubbling via event.stopPropagation();, else, it will bubble and the callback will run.
here's how it ties together after the above:
http://jsfiddle.net/dimitar/nAb6N/13/
(function() {
var opener = $('opendiv');
var boxtoopen = $('box');
boxtoopen.set('morph', {
duration: 700,
transition: 'bounce:out'
});
boxtoopen.addEvent('outerClick', function(event) {
boxtoopen.morph(".openOff");
opener.removeClass("hide");
});
opener.addEvent('click', function(e) {
e.stop();
boxtoopen.morph(".openOn");
this.addClass("hide");
});
})();
I have also 'outsourced' the morph properties to the CSS as it makes more sense, semantically.
P.S. note that you need mootools 1.4.3 or 1.4.5, but not 1.4.4 as there's a morph bug to do with units in that release. the jsfiddle above uses 1.4.6 (mootools edge).
How to trigger an event in Mootools for a specific tag/element with a specific element ID?
I have this:
Video
This rel="rokbox" means that the element will be used by the Mootools RokBox modal box, but I've hidden the link.
Now, I've added this code:
window.onload = function() {
if(document.readyState == 'complete') {
// point of execution
// here I want to trigger the "a" element I've wrote up before
}
}
The code reaches until the "point of execution", when I set a basic alert, or whatsoever.
window.addEvent('domready', function() {
$('video_popup').fireEvent('click');
});
Note the use addEvent/domready, which is the proper method to add a function which must execute once the page is ready.
I know that onload event waits for page resources to load before firing - images, stylesheets, etc.
But does this include IFrames inside the page? In other words, is it guaranteed that all the child Frames' onloads will always fire before the parent's does?
Also, please let me know if behavior varies between browsers.
No, it doesn't. If you want to do something like that, you'll need to add an onload handler for the iframe. You can do this nicely with jQuery:
<iframe src="http://digg.com"></iframe>
<script>
var count = $('iframe').length;
$(function() {
// alert('loaded'); // will show you when the regular body loads
$('iframe').load(function() {
count--;
if (count == 0)
alert('all frames loaded');
});
});
</script>
This would alert when all the frames are loaded.
See the example:
http://jsbin.com/azilo
Or plain javascript should work..
function checkIframes() {
if(!i) { i = 0; }
if(document.getElementsByTagName('iframe')[i]) {
document.getElementsByTagName('iframe')[i].onload = function () { i++; checkIframes(); }
}
else { yourFunctionInHere(); }
}
haven't really tested this, but should work... than refer to it with document.onload = function() { checkIframes(); }
I don't really like libraries like jQuery, because so far I found I can achieve more with less code, with regular javascript.
As I see on my pages, each iframe got independent onload, and top-frame onload doesn't wait for iframes to fire.
I got gif/png banners on my site that sometimes loads very slowly, so I put them into iframe and that made whole site and onload event to work faster.