It seems disabled button "onclick" function is still fired when triggering it programmaticaly, eg:
<div>
<input type="button" onclick="save()" id="saveButton" value="save" disabled="disabled" />
<input type="button" onclick="byPassDisabled()" value="bypass disabled button"/>
<div id="counter">0</div>
function save(){
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
function byPassDisabled(){
$('#saveButton').click();
}
see http://jsfiddle.net/WzEvs/363/
In my situation, keyboards shortcuts are bound to functions triggering the ".click()" on buttons. I'll find it very annoying to have to disable the shorcuts or check if the button is disabled myself. I'd prefer a general solution fixing this problem.
But why? This behavior doesn't seem fair to me.
Any workaround?
The attribute only disables user interaction, the button is still usable programmatically.
So yeah, you gotta check
function byPassDisabled(){
$('#saveButton:enabled').click();
}
Alternatively don't use inline handlers.
$(document).on('click', '#saveButton:enabled', function(){
// ...
});
For future use...the OP code works because jQuery will still call it's own handlers even if the DOM element is disabled. If one were to use vanilla javascript, the disabled attribute would be honored.
const element = document.getElementById('saveButton');
element.click() //this would not work
You can programmatically trigger click on a disabled button.
There are ways to find if the event is a click on button by user or it has been trigger programmatically. http://jsfiddle.net/WzEvs/373/
$(function () {
$("#saveButton").on('click', function (e) {
if (!e.isTrigger) {
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
});
$("#bypassButton").on('click', function (e) {
$("#saveButton").click();
});
});
e.isTrigger is true if you call the click() programmatically. Basically you are triggering the click event manually in code.
You can trigger click still although made it disable .As Spokey said it just shows the user-interaction(the usability still persists that can be turned on programmatically) .
off or unbind the click will solve this issue.
Thanks
Related
Thanks for any help with this. Basically I have a stop button on a timer - and I need to have it be activated via a key press instead of or in addition to being able to click it with mouse. I've tried a few different ways using document.addeventlistener for example but nothing I have done has worked. Below is the relevant HTML/JS. Can anyone point me in the right direction of how I should best go about this? For example ideally I will press a number on the num pad to stop my counter. I'm not sure how to separate the two lines of code in the block format wise below, but just know button is in its proper html tags and the stop button is within script tags.
Thank you
<button id="stop" class="btn btn-danger">STOP</button>
/* Stop button */
stop.onclick = function() {
clear = true;
start.disabled = false;
stop.disabled = true;
}
Here, I created an example for the keydown event. Use tab key navigate to stop button and then press enter key it will get disabled.
document.getElementById("stop").addEventListener("keypress", stopTimer, false);
function stopTimer() {
document.getElementById("stop").setAttribute('disabled', true);
}
<button id="stop">STOP</button>
For the button element, click event has triggered on both, click and keypress as you can see below (this happen when you press spacebar or return, with another key just trigger keypress event); but on anyway you can set more than one event on your element.
document.getElementById("stop").addEventListener("click",function(){
console.log('Clicked!');
});
document.getElementById("stop").addEventListener("keypress",function(){
console.log('Keypressed!');
});
<button id="stop">Stop!</button>
if you need no-mouse interaction, you have to focus the element...
document.getElementById("stop").addEventListener("click",function(){
console.log('Clicked!');
});
document.getElementById("stop").addEventListener("keypress",function(){
console.log('Keypressed!');
});
document.getElementById("stop").focus();
<button id="stop">Stop!</button>
I've been working on trying to trigger an onchange listener with java script in Mozilla Firefox. I've found a lot on Stack Overflow posted about this, but nothing seems to be working for my unique case.
I've created this HTML with a onchange listener from an onchange event using this helpful post (JavaScript OnChange Listener position in HTML markup). Here's my code:
<HTML>
<head>
<script type="text/javascript">
window.onload= function () {
if(window.addEventListener) {
document.getElementsByClassName('search-box')[0].addEventListener('change', loadXMLDoc, false);
} else if (window.attachEvent){
document.getElementsByClassName('search-box')[0].attachEvent("onchange", loadXMLDoc);
}
function loadXMLDoc(){
alert('It worked');
}
}
function addTextCallListener() {
var searchBox = document.getElementsByClassName("search-box")[0];
searchBox.value = "Hello";
}
</script>
</head>
<BODY>
<input type="text" class="search-box" placeholder="Player Search">
<br \>
<button type="button" onclick="addTextCallListener()">Click Me!</button>
</BODY>
</HTML>
I also saved it as this jsfiddle (for some reason I had to keep it all together for it to work, I couldn't break it up into js and html).
https://jsfiddle.net/josephfedor42/crogL0zd/1/
If you play with this jsfiddle you can see that entering text and pressing enter will trigger the listener and the pop up with the message “It worked” will appear.
But if the button “Click Me!” is pressed it only changes the value of the text box, and the onchange listener is not called.
I realize I could easily add an onchange event to this button. But I want to to trigger the listener by programatically/ superficially using javascript in my addTextCallListener() function.
I've tried the simple stuff, like calling
searchBox.onchange();
searchBox.focus();
searchBox.click();
And a combination of these to add and remove the focus. But it doesn't seem to work. I've found quite a few posts on triggering an onchange event, but nothing that works in Firefox.
Any help would be appreciated.
Thanks for that link of a possible duplicated question. I had checked out that link before.
But I gave it a try again. I saved the jsfiddle from them both and neither one work.
My implementation of Dorian's answer
https://jsfiddle.net/josephfedor42/zaakd3dj/
My implementation of Alsciende's answer
https://jsfiddle.net/josephfedor42/xhs6L6u2/
emphasize mine
According to the mdn page about the change event,
The change event is fired for <input>, <select>, and <textarea>
elements when a change to the element's value is committed by the
user.
and to whatwg specs :
When the input and change events apply (which is the case for all
input controls other than buttons and those with the type attribute in
the Hidden state), the events are fired to indicate that the user has
interacted with the control.
Therefore, setting the value of an input is not an action "committed by the user" nor a sign that "the user has interacted with the control", since it was made by the code.
So, even if the specifications for this event are kind of unclear, the event should not fire when you change its value by code.
Something like this should work:
function addTextCallListener() {
var searchBox = document.getElementsByClassName("search-box")[0];
searchBox.value = "Hello";
//fire the event
if (document.createEvent) {
searchBox.dispatchEvent('change');
} else {
searchBox.fireEvent("onchange");
}
}
Here is the code I needed to add to my function addTextCallListener:
var evObj = document.createEvent('HTMLEvents');
evObj.initEvent( 'change', true, true );
searchBox.dispatchEvent(evObj);
I updated the jsfiddle. The working code is here https://jsfiddle.net/josephfedor42/crogL0zd/7/
Replace onchange with change in this part:
document.getElementsByClassName('search-box')[0].attachEvent("onchange", loadXMLDoc);
The custom CSS class .btn-loading disables the button and sets its text to loading state:
$(document).on('click', '.btn-loading', function() {
var btn = $(this);
btn.button('loading');
// Fail-safe for buttons that get stuck in the loading state sometimes.
setTimeout(function() {
Rollbar.error("Button stuck");
btn.button('reset');
}, 10000);
});
// Be sure to remove any loading state on page refresh
$(document).on('ready page:load', function() {
$('.btn-loading').button('reset');
});
Example button
button type="submit" class="btn btn-primary btn-loading" data-loading-text="Processing..." Continue
When the button is pressed, text is changed to 'Processing...' and the button is disabled preventing multiple submits.
However, sometimes in development and production, the button gets stuck in the loading state and for some reason does not cause the submit and/or rendering of the new page. The setTimeout is firing multiple times a day on the production server. We are having hard times producing the problem on the development consistently.. it happens randomly now and then.
Rollbar's statistics shows that it's not browser specific nor a single button+action that's causing it. So the cause is not a slow server response either.
Any idea what might be causing this and how to fix it?
I faced similar problem some time back and solved the same with a different approach. Try to follow the below steps to solve your problem.
HTML:
Change your button type from “Submit” to “Button”. This will give you full control to execute your scripts.
<button type="button" class="btn btn-default" id=”SubmitButton”>Submit</button>
JQUERY:
On Button Click, you need to disable the button. This will immediately stop users to click again. Then you can change the button text to "Processing". Below script will guide you make it happen.
$(function () {
$('#SubmitButton').click(function (e) {
e.preventDefault();
//Disable Button to avoid multiple clicks
$(this).attr("disabled", true);
// Change the button text to “Processing”
$(this).text(‘Processing’);
// Write Your Validation Scripts
// If Validation Fails - $(this).text(‘Submit’); $(this).attr("disabled", '');
// Else Submit Form
//Submit the Form
$("#targetForm").submit();
})
})
To prevent multiple submit you can use $.one() function also. and add remaining logic.
When the button is pressed, text is changed to 'Processing...' and the
button is disabled preventing multiple submits.
-- Note that there's not part in your code snippet that disables the button.
// Fail-safe for buttons that get stuck in the loading state sometimes.
setTimeout(function() {
// if(stuck){
Rollbar.error("Button stuck");
btn.button('reset');
// } // end-if
}, 10000);
-- It looks like your fallback will always be executed. Shouldn't be executed when the button is stuck?
The setTimeout is firing multiple times a day on the production
server.
-- Because your button is never disabled, and because there is no condition restricting it from firing on being clicked.
Moreover, there's no jQuery method like button(). It looks like you're using jQueryUI, which you should have mentioned as well. But jQueryUI + Bootstrap seem like a weird combination, to me.
Here is my alloy code - snippet:
<RightNavButton>
<Button id="btnRight" onClick="rightButtonClicked" />
</RightNavButton>
JS:
//edit profile button
function rightButtonClicked(e) {
Ti.API.info("testing bubble ");
//TODO: add functionality here
e.cancelBubble = true;
}
The event still bubbles. Normal buttons this works fine.
Thanks
Update:
<RightNavButton>
<Button id="btnRight" title='Chat' onClick="rightButtonClicked" bubbleParent='false'/>
</RightNavButton>
Still bubbles. i.e. if I click on that multiple times, it keeps on opening windows. Rather then wait for event to finish and then fire again.
Try
e.stopImmediatePropagation();
you should used bubbleParent property over the button, set it to false it will work. Here is the documentation
I'm working on a project with an autocomplete searchbox. Now I have the issue that I want to pass the value from the found autocompleteresults to the input box, but on the same time, I want the autocompletebox to hide when the inputfield is not more focused.
Now I have a conflict going on with both of them since the click on the autocompletebox is seen as focusout and hide the box even before it can pass the value. Any pointers or workarounds for this kind of issue? Here a jsfiddle to make it more clear to you.
http://jsfiddle.net/KeGvM/
Or here
CSS:
#a_c {display:none;}
JS:
$('#search_field').focusout(function() {
$('#a_c').hide(); // IF I DELETE THIS IT WORKS
});
$('#search_field').focusin(function() {
$('#a_c').show();
});
$('#a_c a').click(function() {
$('#search_field').val('');
var value = $(this).text();
var input = $('#search_field');
input.val(input.val() + value);
$('#a_c').hide();
return false;
});
HTML:
<input autocomplete="off" onkeyup="searchFor(this.value);" name="search" id="search_field" class="bold" type="text" placeholder="Search...">
<div id="a_c">hello world</div>
The way I solved this was using the mousedown event instead of click. The mousedown event is always triggered before the focusout event while click is not.
You can try it out in the little demo below. Focus on the field and then click on the button.
const field = document.getElementById('field');
const btn = document.getElementById('btn');
btn.addEventListener('click', () => console.log('Click'));
btn.addEventListener('mousedown', () => console.log('Mouse down'));
field.addEventListener('focusout', () => console.log('Focus out'));
<input id="field">
<button id="btn">Try it</button>
As you can see the output is in the following order:
Mouse down
Focus out
Click
This is the most stable solution without using any workaround hacks like timeouts. It also does not depend on jQuery. The only thing worth noting that mousedown does not wait for the user to release their mouse button, but in terms of user experience that is not really a concern here.
How about using
:hover
I solved same problem using it.
$('className').on('focusout', function(e) {
if($('.suggestLi' + ':hover').length) {
return;
}
$('.suggestList').empty();
});
My solution in the similar situation was using timeout to temporarily hold off the action taken in blur event handler. Like this:
$('#search_field').focusout(function() {
window.setTimeout(function() { $('#a_c').hide() }, 100);
});