How to determine the current state of a HTML Button - javascript

From plain javascript, how can I tell if a <button> is currently pressed or not?
It isn't sufficient to use mouse events, because the button could be pressed due to an alternate input method, such as a key press, or maybe even some other accessibility method that somebody invents in the future (tablets come to mind).
But in searching the properties and attributes of the button element, I don't see anything showing the buttons current state.

I'm a bit late, but I stumbled over the same question so here I am. Maybe this still can be helpful to others. According to the HTML specification the button element doesn't have a state. If a button is currently pressed or not is a matter of CSS. The CSS specification defines that the :active pseudo-class applies while an element is being activated by the user. So the questions boils down to how to get that class with javascript. This can be done with
this == document.activeElement
where this is the button. The statement is true if the button is active.
It actually makes sense that a button, other than a checkbox, doesn't keep a state.

Combine event handlers. Demo here: http://jsbin.com/horeq/2/edit
HTML
<button id="a">Button</button>
<pre id="output"></pre>
jQuery
var output = $('#output'),
btn = $('button#a');
var active;
btn.on('mousedown keydown', function(data) {
active = 'on';
output.html(active);
})
btn.on('mouseup keyup', function(data) {
active = 'off';
output.html(active);
})
JS (Could be more efficient)
var output = document.getElementById('output'),
btn = document.getElementById('a');
var active;
btn.addEventListener('keydown', function(data) {
active = 'on';
output.innerHTML = active;
});
btn.addEventListener('keyup', function(data) {
active = 'off';
output.innerHTML = active;
});
btn.addEventListener('mousedown', function(data) {
active = 'on';
output.innerHTML = active;
});
btn.addEventListener('mouseup', function(data) {
active = 'off';
output.innerHTML = active;
});

Add "onclick"-tag to your code.
<input type="button" name="button" value="button" onclick="myfunction()">
Now device run javascript-function, if button are clicked!

Related

basic javascript question about disabling buttons

I have a simple piece of javascript embedded into my html form, not a separate file, that is supposed to disable the submit form button until a certain checkbox has been checked but it doesn't seem to be working.
<script>
var disclaimer = document.getElementById("disclaimer");
var submitButton = document.getElementById("submit");
submitButton.disabled = true;
if (disclaimer.checked) {
submitButton.disabled = false;
}
</script>
which I wrote and seems simple and effective but I'm not getting the results I'm looking for. After researching I see results such as
$('#check').click(function(){
if($(this).attr('checked') == false){
$('#btncheck').attr("disabled","disabled");
}
else
$('#btncheck').removeAttr('disabled');
});
Now obviously the variable names and such are named differently but this doesn't even look remotely similar to the javascript code I've provided above and I'm having a hard time getting useful tips from the apparently working code below that does the same thing. Could someone break down the code segment below such that I might be able to fix my code above?
This is the snippet of code with the two HTML id's in question,
<label style='font-size: smaller;'>
<input type='checkbox' name='disclaimer' id='disclaimer' required='required' />
I understand that by submitting this form,
I am transferring any copyright and intellectual property rights to the form's owner,
that I have the right to do so,
and that my submission is not infringing on other people's rights.
</label><br/>
<script>
var disclaimer = document.getElementById("disclaimer");
var submitButton = document.getElementById("submit");
submitButton.disabled = true;
if (disclaimer.checked) {
submitButton.disabled = false;
}
</script>
<div class='vspace'/>
<input type='submit' id='submit' name='came-from-form'/>
Edit: Tons of great answers below that were very informative for letting me know what I'm working with. The issue I'm now facing is implementing these things. In the snippets below this seems very easy to implement but as I try to implement each answer below I'm not seeing any results which clearly means I'm doing something wrong somewhere else in my form. I've attached a larger snippet of the code in question if it helps. Otherwise it might be best to ask a new question.
I believe you trying to find the solution in vanilla JavaScript.
You have to attach the event to the check element like the following way:
var disclaimer = document.getElementById("disclaimer");
document.getElementById("submit").disabled = true;
disclaimer.addEventListener('click', function(){
var submitButton = document.getElementById("submit");
submitButton.disabled = true;
if (this.checked) {
submitButton.disabled = false;
}
});
<form>
<input type="checkbox" id="disclaimer"/>
<button id="submit">Submit</button>
</form>
Update:
In your code, the script is executing before the DOM is fully loaded. Hence you get a error:
Uncaught TypeError: Cannot set property 'disabled' of null
You can either place the script at the end or wrap your code with
DOMContentLoaded
The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. A very different event load should be used only to detect a fully-loaded page. It is an incredibly common mistake to use load where DOMContentLoaded would be much more appropriate, so be cautious.
<label style='font-size: smaller;'>
<input type='checkbox' name='disclaimer' id='disclaimer' required='required' />
I understand that by submitting this form,
I am transferring any copyright and intellectual property rights to the form's owner,
that I have the right to do so,
and that my submission is not infringing on other people's rights.
</label><br/>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
var disclaimer = document.getElementById("disclaimer");
document.getElementById("submit").disabled = true;
disclaimer.addEventListener('click', function(){
var submitButton = document.getElementById("submit");
submitButton.disabled = true;
if (this.checked) {
submitButton.disabled = false;
}
});
});
</script>
<div class='vspace'/>
<input type='submit' id='submit' name='came-from-form'/>
Quick Explantion
Here's a quick explanation of the code, which is heavily reliant on the JavaScript library, jQuery:
// click() is called every time the element `id="check"` is clicked
$('#check').click(function(){
// if element with `id="check"` has an attribute called *checked* set to false or it is null, then perform the if-block, otherwise perform the else-block
if($(this).attr('checked') == false){
// set disabled attribute of element with `id="btncheck"` to value of `disabled`
$('#btncheck').attr("disabled","disabled");
}
else
// remove disabled attribute of element with `id="btncheck"`
$('#btncheck').removeAttr('disabled');
});
anything in $() is selecting the element in the DOM, primarily using CSS-like selectors
.attr() is a method that gets/sets the element HTML attribute
.removeAttr() is a method that removes the HTML attribute
Vanilla JS
What you want to accomplish can be done with vanilla JS.
const disclaimer = document.querySelector("#disclaimer");
const submit = document.querySelector("#submit");
submit.disabled = true; // default setting
const clickHandler = (event) => submit.disabled = !event.target.checked;
disclaimer.addEventListener('click', clickHandler ); // attach event
<form>
<input type="checkbox" id="disclaimer"/>
<button id="submit">Submit</button>
</form>
Hope this will work for you
$('#disclaimer').click(function(){
if($(this).attr('checked') == false){
$('#submit').attr("disabled","disabled");
}
else
$('#submit').removeAttr('disabled');
});
Here if condition indicates the action which should be done if the disclaimer is not chcked. Button will be enable if the disclaimer is checked.
If you want jQuery, use prop (is not wrong to use attr too but I prefer prop instead).
For checkbox, use change event instead of click. I'd do like:
$('#check').on("change", function(){
var isChecked = $(this).is(':checked');
$('#btncheck').prop("disabled", !isChecked);
});
The only significant difference between the 2 code samples you posted is that the second one wraps the button disabling in the click event.
First one says : Straight when page is loaded, if the checkbox is checked, enable the button. (hint: happens only once)
Second one says : For each click on the checkbox, if the checkbox is checked, enable the button.
Something like this should work (haven't tested) :
<script>
var disclaimer = document.getElementById("disclaimer");
var submitButton = document.getElementById("submit");
function disableSubmitIfDisclaimerNotAccepted(){
submitButton.disabled = true;
if (disclaimer.checked) {
submitButton.disabled = false;
}
}
disclaimer.onclick = disableSubmitIfDisclaimerNotAccepted; // everytime the checkbox is clicked
disableSubmitIfDisclaimerNotAccepted(); // on page load
</script>
You must listen to input events in order to make changes when something change, like checking an checkbox.
var disclaimer = document.getElementById("disclaimer");
var submitButton = document.getElementById("submit");
submitButton.disabled = true;
disclaimer.addEventListener('change', function() {
if (this.checked) {
submitButton.disabled = false;
} else {
submitButton.disabled = true;
}
})
More about events: https://developer.mozilla.org/en-US/docs/Web/Events
Submit button disabled by default in HTML :
<input type="checkbox" id="disclaimer">
<label for="disclaimer">Disclaimer</label>
<input type="submit" id="submit" disabled>
Simplest solution using ES6 syntax without JQuery :
let disclaimerCheckbox = document.getElementById('disclaimer'),
submitButton = document.getElementById('submit');
disclaimerCheckbox.onchange = () => submitButton.disabled = !disclaimerCheckbox.checked;
JSFiddle
NOTE : no need to use the DOMContentLoaded event if the script has the defer attribute.

clear click queue from jQuery

I have a click event that triggers other click events that adds an element to the DOM.
EDIT: But when I click it a second time two elements get added and third time two elements get added. When I check the jQuery queue it confirms that I have added an event to the queue that fires every time.
What I try to accomplish is to add a click event to two dropdownlists by clicking another element.
$(".step-1 a").on("click", function(e){
e.preventDefault();
var userValue = $(this).attr('id');
$(".template-image").removeClass("selected");
$(this).children(":first").addClass("selected");
$("#page_template option ").each(function(){
var t = $(this);
var cValue = t.attr("value");
if(t.attr("selected") === "selected"){
t.removeAttr("selected");
}
if(t.attr("value") === userValue ){
t.prop("selected", "selected");
$('#page_template').trigger('change');
var template = t.attr("value");
switch (template)
{
case "default":
$(".step-2").slideDown("fast");
$(".step-2").addClass("show");
break;
default:
$(".step-2").removeClass("show");
$(".step-2").slideUp("fast");
break;
}
}
});
});
$('.step-2 img').on("click", function(e){
e.preventDefault();
var userinput = $(this).attr('id');
$('.flexible-footer .acf-fc-add').each(function(){
var text = $(this).text();
if(text === "Add columns"){
$(this).trigger('click');
$('.flexible-footer .acf-fc-popup ul li a').each(function(){
var column = $(this).attr('data-layout');
if (column === userinput) {
$(this).trigger('click');
$(this).finish();
console.log($(this).queue());
}
});
}
});
It sounds like you're assigning click events multiple times on the same elements. A simple solution to this problem is to use the jQuery function off() to remove the old click-event before adding a new one. Or make sure you're only adding the click event to new element that doesn't already have them. You can do it like this:
$('img.or-whatever').off('click').on('click', function(ev){...});
Or maybe use namespaces for increased readability:
$('img.or-whatever').off('click.custom-namespace').on('click.custom-namespace', function(ev){...});
It might not be the correct answer to your question, but it might be a solution.
Edit:
If you just want to clear the event queue, you could try clearQueue().

Cycling Event Listeners vs many Listeners

I'm doing some work with a program that has quite a lot to click, however somethings only need to be clicked when say their parent has been clicked on and is active. Now there are three ways as I see it to approach this.
Many event handlers
Constantly Create and Destroy them
Have one top-level handler and read the Event for what child even occurred on (event.target)
The reason three is not the most obvious choice for me is that children of what I clicked would be event.target and object.parentNode would need to repeatedly run to see what element was in-fact available for clicking; I hear DOM api's are expensive.
I'm interested to know how expensive each method is relative to each other and what is accepted practice in something like that. Number of listeners is in the hundreds range, it's a dynamic application with modest DOM mutation.
EDIT: For clarification this question is about DIV's and attaching event handlers to them.
If you are using buttons or similar you can enable and disable them. They usually have a different appearance too so the user can know not to click on a disabled button.
If you aren't using buttons, you can add or remove a class called disabled. When the element is clicked, the listener can check its class and if it has a class of "disabled", have it do nothing. Otherwise, have it do what it does.
The addition and removal of the class can also be used to modify the appearance of the element, making it look disabled (similar to how buttons and inputs change appearance when disabled).
Simple has/add/removeClass functions:
var util = {dom:{}};
util.trim = function(s) {
return s.replace(/(^\s+)|(\s+$)/g,'').replace(/\s+/g,' ');
}
util.dom.hasClassName = function(el, cName) {
var re = new RegExp('(^|\\s+)' + cName + '(\\s+|$)');
return el && re.test(el.className);
}
util.dom.addClassName = function(el, cName) {
if (!util.dom.hasClassName(el, cName)) {
el.className = util.trim(el.className + ' ' + cName);
}
}
util.dom.removeClassName = function(el, cName) {
if (util.dom.hasClassName(el, cName)) {
var re = new RegExp('(^|\\s+)' + cName + '(\\s+|$)','g');
el.className = util.trim(el.className.replace(re, ''));
}
}
A simple example:
<script>
function toggle(id) {
var el = document.getElementById(id);
if (!el) return;
if (util.dom.hasClassName(el, 'disabled')) {
util.dom.removeClassName(el, 'disabled')
} else {
util.dom.addClassName(el, 'disabled')
}
}
function doStuff(el) {
if (util.dom.hasClassName(el, 'disabled')) return;
alert('I\'m alive!');
}
</script>
<button id="b0" onclick="doStuff(this);">button 0</button>
<button onclick="toggle('b0')">change b0</button>
Alternatively the disabled property could be set to true or false.
You can also maintain state independantly of the elements, so when an element is clicked on it knows what to do based on the state if its child or parent elements (or whatever).

How to know which button is clicked

In my page I have many edit buttons each name starts with "edit" and then some id. I want to know any of my edit buttons is clicked or not.
In details, I have form. In form I have many edit buttons which name starts with "edit" , delete buttons which name starts with "delete" and 1 add button. All are submit buttons. form onsubmit I call JavaScript function in which I want if the button is edit confirm("some text") else submit form.
How can I do that in JavaScript?
I think give all these buttons same id and then getElementById but then how con I change?
This is simple using jQuery:
$(':button').click(function() {
// reference clicked button via: $(this)
var buttonElementId = $(this).attr('id');
});
Try it out:
http://jsfiddle.net/7YEay/
UPDATE based on feedback in comments
This is untested/pseudo code:
$(':submit').click(function(event) {
var buttonName = $(this).attr('name');
if (buttonName.indexOf('edit') >= 0) {
//confirm("some text") logic...
}
event.preventDefault();
});
This documentation may be helpful too: http://api.jquery.com/submit/
function MyOnSubmit(e){
e = e || window.event;
// srcElement for IE, target for w3c
var target = e.target || e.srcElement;
if (target.id.indexOf("edit") > -1){
// an edit button fired the submit event
}
}
although i advice you research further to find a better way to handle edit and delete buttons (like making them links with href=editpage.jsp?id=23)
I'm pretty sure you just answered this yourself...
Each starts with "edit", and ends with a unique ID?
So... $(button).attr("id") would give you that. Store it in a variable? Not sure what you're trying to do..
bind click event on all button:
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
if (button.addEventListener) {
button.addEventListener('click', handler, false);
}
else {
button.attachEvent('onclick', handler);
}
}
in your event handler, get the Event object, and then get the target:
function handler(e) {
e = e || window.event;
// srcElement for IE, target for w3c
var target = e.target || e.srcElement;
var id = target.name.substring(4);
/* your code rely on id */
}
I think you might not have phrased your question correctly. If you are using jquery, locating the button is as easy as $('#id'), and if you want to store any information on that button, you can either add an attribute or use jquery.data function.
$('#id').attr("pressed", "true");
Or
$('#id').data('pressed', 'true');

Change onclick action with a Javascript function

I have a button:
<button id="a" onclick="Foo()">Button A</button>
When I click this button the first time, I want it to execute Foo (which it does correctly):
function Foo() {
document.getElementById("a").onclick = Bar();
}
What I want to happen when I click the button the first time is to change the onclick function from Foo() to Bar(). Thus far, I've only been able to achieve an infinite loop or no change at all. Bar() would look something like this:
function Bar() {
document.getElementById("a").onclick = Foo();
}
Thus, clicking this button is just alternating which function gets called. How can I get this to work? Alternatively, what's a better way to show/hide the full text of a post? It originally starts shorted, and I provide a button to "see the full text." But when I click that button I want users to be able to click the button again to have the long version of the text go away.
Here's the full code, if it helps:
function ShowError(id) {
document.getElementById(id).className = document.getElementById(id).className.replace(/\bheight_limited\b/, '');
document.getElementById(id+"Text").className = document.getElementById(id+"Text").className.replace(/\bheight_limited\b/, '');
document.getElementById(id+"Button").innerHTML = "HIDE FULL ERROR";
document.getElementById(id+"Button").onclick = HideError(id);
}
function HideError(id) {
document.getElementById(id).className += " height_limited";
document.getElementById(id+"Text").className += " height_limited";
document.getElementById(id+"Button").innerHTML = "SHOW FULL ERROR";
document.getElementById(id+"Button").onclick = "ShowError(id)";
}
Your code is calling the function and assigning the return value to onClick, also it should be 'onclick'. This is how it should look.
document.getElementById("a").onclick = Bar;
Looking at your other code you probably want to do something like this:
document.getElementById(id+"Button").onclick = function() { HideError(id); }
var Foo = function(){
document.getElementById( "a" ).setAttribute( "onClick", "javascript: Boo();" );
}
var Boo = function(){
alert("test");
}
Do not invoke the method when assigning the new onclick handler.
Simply remove the parenthesis:
document.getElementById("a").onclick = Foo;
UPDATE (due to new information):
document.getElementById("a").onclick = function () { Foo(param); };
Thanks to João Paulo Oliveira, this was my solution which includes a variable (which was my goal).
document.getElementById( "myID" ).setAttribute( "onClick", "myFunction("+VALUE+");" );
I recommend this approach:
Instead of having two click handlers, have only one function with a if-else statement. Let the state of the BUTTON element determine which branch of the if-else statement gets executed:
HTML:
<button id="a" onclick="toggleError(this)">Button A</button>
JavaScript:
function toggleError(button) {
if ( button.className === 'visible' ) {
// HIDE ERROR
button.className = '';
} else {
// SHOW ERROR
button.className = 'visible';
}
}
Live demo: http://jsfiddle.net/simevidas/hPQP9/
You could try changing the button attribute like this:
element.setAttribute( "onClick", "javascript: Boo();" );
What might be easier, is to have two buttons and show/hide them in your functions. (ie. display:none|block;) Each button could then have it's own onclick with whatever code you need.
So, at first button1 would be display:block and button2 would be display:none. Then when you click button1 it would switch button2 to be display:block and button1 to be display:none.
For anyone, like me, trying to set a query string on the action and wondering why it's not working-
You cannot set a query string for a GET form submission, but I have found you can for a POST.
For a GET submission you must set the values in hidden inputs e.g.
an action of: "/handleformsubmission?foo=bar"
would have be added as the hidden field like: <input type="hidden" name="foo" value="bar" />
This can be done add dynamically in JavaScript as (where clickedButton is the submitted button that was clicked:
var form = clickedButton.form;
var hidden = document.createElement("input");
hidden.setAttribute("type", "hidden");
hidden.setAttribute("name", "foo");
hidden.setAttribute("value", "bar");
form.appendChild(hidden);
See this question for more info
submitting a GET form with query string params and hidden params disappear

Categories

Resources