I have a form, containing a <select> element containing options which are changing according to another field value.
So, when the <select> item gains focus if the other field value is not set blur event is triggered on the previous, and focus is triggered on the latter.
Here's a simplified version of my code:
$(document).on('focus', '#requiresOuterValue',
function() {
if( isNaN(parseInt( $('#outerValue').val() )) )
{
$('#outerValue').trigger('focus');
}
});
The code works fine (dropdown content disappears, #outerValue gains focus) in Firefox but not in chrome, where #outerValue gains focus, but the <select> item contents are displayed as well.
Mmm.. Did you tried to use the native 'focus' method instead the 'focus' jquery event?
$('#outerValue')[0].focus();
I'm not sure that triggering jQuery events have implicit browser native behaviours.
Well, I came up with a solution.
Your problem is that the closure of a select is not standard in all browsers. the only way I found to simulate the closure is to re-render the select.
Here is the code:
$(document).on('focus', '#requiresOuterValue', function() {
var requiresOuterValue = $("#requiresOuterValue").clone();
if( isNaN(parseInt( $('#outerValue').val() )) )
{
$('#outerValue').trigger('focus');
$("#requiresOuterValue").replaceWith(requiresOuterValue);
}
});
EDIT: fiddle here http://jsfiddle.net/JonnyMe/C9rKL/1/
jQuery plugin implementation
You can even implement a jQuery plugin to achieve the goal:
$.fn.closeSelect = function() {
if($(this).is("select")){
var fakeSelect = $(this).clone();
$(this).replaceWith(fakeSelect);
}
};
And then use it this way:
$(document).on('focus', '#requiresOuterValue', function() {
if( isNaN(parseInt( $('#outerValue').val() )) )
{
$('#outerValue').trigger('focus');
$("#requiresOuterValue").closeSelect();
}
});
Related
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 use this jQuery code to set the mouse pointer to its busy state (hourglass) during an Ajax call...
$('body').css('cursor', 'wait');
and this corresponding code to set it back to normal...
$('body').css('cursor', 'auto');
This works fine... on some browsers.
On Firefox and IE, as soon as I execute the command, the mouse cursor changes. This is the behavior I want.
On Chrome and Safari, the mouse cursor does not visibly change from "busy" to "auto" until the user moves the pointer.
What is the best way to get the reluctant browsers to switch the mouse pointer?
It is a bug in both browsers at the moment. More details at both links (in comments as well):
http://code.google.com/p/chromium/issues/detail?id=26723
and
http://code.google.com/p/chromium/issues/detail?id=20717
I would rather do it more elegantly like so:
$(function(){
$("html").bind("ajaxStart", function(){
$(this).addClass('busy');
}).bind("ajaxStop", function(){
$(this).removeClass('busy');
});
});
CSS:
html.busy, html.busy * {
cursor: wait !important;
}
Source: http://postpostmodern.com/instructional/global-ajax-cursor-change/
I believe this issue (including the mousedown problem) is now fixed in Chrome 50.
But only if you are not using the developer tools!!
Close the tools and the cursor should immediately respond better.
I got inspired from Korayem solution.
Javascript:
jQuery.ajaxSetup({
beforeSend: function() {
$('body').addClass('busy');
},
complete: function() {
$('body').removeClass('busy');
}
});
CSS:
.busy * {
cursor: wait !important;
}
Tested on Chrome, Firefox and IE 10. Cursor changes without moving the mouse. "!important" is needed for IE10.
Edit: You still have to move cursor on IE 10 after the AJAX request is complete (so the normal cursor appear). Wait cursor appears without moving the mouse..
Working solution on CodeSandbox
Some of the other solutions do not work in all circumstances. We can achieve the desired result with two css rules:
body.busy, .busy * {
cursor: wait !important;
}
.not-busy {
cursor: auto;
}
The former indicates that we are busy and applies to all elements on the page, attempting to override other cursor styles. The latter applies only to the page body and is used simply to force a UI update; we want this rule to be as non-specific as possible and it doesn't need to apply to other page elements.
We can then trigger and end the busy state as follows:
function onBusyStart() {
document.body.classList.add('busy');
document.body.classList.remove('not-busy');
}
function onBusyEnd() {
document.body.classList.remove('busy');
document.body.classList.add('not-busy');
}
In summary, although we have to change the cursor style to update the cursor, directly modifying document.body.style.cursor or similar does not have the intended effect, on some engines such as Webkit, until the cursor is moved. Using classes to affect the change is more robust. However, in order to reliably force the UI to update (again, on some engines), we have to add another class. It seems removing classes is treated differently from adding them.
First of all, you should be aware that if you have a cursor assigned to any tag within your body, $('body').css('cursor', 'wait'); will not change the cursor of that tag (like me, I use cursor: pointer; on all my anchor tag). You might want to look at my solution to this particular problem first : cursor wait for ajax call
For the problem that the cursor is only updated once the user move the mouse on webkit browsers, as other people said, there is no real solution.
That being said, there is still a workaround if you add a css spinner to the current cursor dynamically. This is not a perfect solution because you don't know for sure the size of the cursor and if the spinner will be correctly positioned.
CSS spinner following the cursor: DEMO
$.fn.extend(
{
reset_on : function(event_name, callback)
{ return this.off(event_name).on(event_name, callback); }
});
var g_loader = $('.loader');
function add_cursor_progress(evt)
{
function refresh_pos(e_)
{
g_loader.css({
display : "inline",
left : e_.pageX + 8,
top : e_.pageY - 8
});
}
refresh_pos(evt);
var id = ".addcursorprog"; // to avoid duplicate events
$('html').reset_on('mousemove' + id, refresh_pos);
$(window).
reset_on('mouseenter' + id, function(){ g_loader.css('display', 'inline'); }).
reset_on('mouseleave' + id, function(){ g_loader.css('display', 'none'); });
}
function remove_cursor_progress(evt)
{
var id = ".addcursorprog";
g_loader.css('display', 'none');
$('html').off('mousemove' + id);
$(window).off('mouseenter' + id).off('mouseleave' + id);
}
$('.action').click(add_cursor_progress);
$('.stop').click(remove_cursor_progress);
You will need to check if it is a touch device as well var isTouchDevice = typeof window.ontouchstart !== 'undefined';
In conclusion, you better try to add in your page a static spinner or something else that shows the loading process instead of trying to do it with the cursor.
Korayem's solution works for me in 100% cases in modern Chrome, Safari, in 95% cases in Firefox, but does not work in Opera and IE.
I improved it a bit:
$('html').bind('ajaxStart', function() {
$(this).removeClass('notbusy').addClass('busy');
}).bind('ajaxStop', function() {
$(this).removeClass('busy').addClass('notbusy');
});
CSS:
html.busy, html.busy * {
cursor: wait !important;
}
html.notbusy, html.notbusy * {
cursor: default !important;
}
Now it works in 100% cases in Chrome, Safari, Firefox and Opera.
I do not know what to do with IE :(
I don't think you'll be able to do it.
However, try changing the scroll position; it might help.
HERE is my solution:
function yourFunc(){
$('body').removeClass('wait'); // this is my wait class on body you can $('body').css('cursor','auto');
$('body').blur();
$('body').focus(function(e){
$('body')
.mouseXPos(e.pageX + 1)
.mouseYPos(e.pageX - 1);
});
}
As of jquery 1.9 you should ajaxStart and ajaxStop to document. They work fine for me in firefox. Have not tested in other browsers.
In CSS:
html.busy *
{
cursor: wait !important;
}
In javaScript:
// Makes the mousecursor show busy during ajax
//
$( document )
.ajaxStart( function startBusy() { $( 'html' ).addClass ( 'busy' ) } )
.ajaxStop ( function stopBusy () { $( 'html' ).removeClass( 'busy' ) } )
Try using the correct css value for the cursor property:
$('body').css('cursor','wait');
http://www.w3schools.com/CSS/pr_class_cursor.asp
I haven't tried this, but what about if you create a transparent div that is absolutely positioned and fills the viewport just before changing the CSS. Then, when the css is changed on the body, remove the div. This might trigger a mouseover event on the body, which might cause the cursor to update to the latest CSS value.
Again, I haven't tested this, but it's worth a shot.
Hey Guys, I have a nitty gritty solution which works on all browsers. Assumption is protoype library is used. Someone can write this as plain Javascript too. The solution is to have a div on top of all just after you reset the cursor and shake it a little bit to cause the cursor to move. This is published in my blog http://arunmobc.blogspot.com/2011/02/cursor-not-changing-issue.html.
$('*').css('cursor','wait'); will work everywhere on the page including links
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).
I have a div with a hidden child. Clicking in the div will toggle the visibility of the child. This works well.
Now the user wants to select some text in the child. Dragging the selection works but as soon as the mouse button is released, the div closes (because of the inClick handler).
If possible, I'd still like to be able to close the div from anywhere in the child because the child can be quite large (hundreds of lines, so it would be tedious to scroll to the div to toggle the child).
Needs to work with IE6+ and all sane browsers. I can't use jQuery directly :-( but I can copy code from jQuery so if jQuery had a solution, I clone it.
Suggestions?
You can do a check on window.getSelection() to see if it contains anything before closing your inner div.
For IE6 you'll want to substitute this with document.selection.
Note that this is proprietry to IE so you'll want to distinguish which method to use via object detection.
Working Demo
You could have a toggle control on the side of the DIV:
toggle.onclick = function () {
if ( this.className === 'closed' ) {
this.className = '';
content.style.display = '';
} else {
this.className = 'closed';
content.style.display = 'none';
}
};
Live demo: http://jsfiddle.net/HcVfW/
I have a Prototype snippet here that I really want to see converted into Mootools.
document.observe('click', function(e, el) {
if ( ! e.target.descendantOf('calendar')) {
Effect.toggle('calendar', 'appear', {duration: 0.4});
}
});
The snippet catches clicks and if it clicks outside the container $('calendar') should toggle.
Are you trying to catch clicks anywhere in the document? Maybe you could try...
var calendar = $('calendar');
$$('body')[0].addEvent('click', function(e) {
if (!$(e.target).getParent('#calendar')) {
var myFx = new Fx.Tween(calendar, {duration: 400});
myFx.set('display', 'block');
}
}
I'm not sure how you are toggling visibility but the way Fx.Tween.set works allows you to change any CSS property. You may want to look at http://mootools.net/docs/core/Fx/Fx.Tween for other possibilities.
Also, notice that I wrapped e.target using a $. This is specifically for IE. I wrote a post about this here under the sub-heading "Mootools Events Targets".
Lastly, I factored out $('calendar') so that you are not searching the DOM every time.