How to automatically disable a text field after checkbox is ticked - javascript

I am currently working on a project, that requires me to implement the following:
I've got 2 input fields - a regular text field, and a checkbox.
What I want to do is - if the user fills in the text field, the checkbox should be automatically disabled. If the checkbox is checked instead, the text field should be disabled.
What I've come up with so far is:
<input type="text" name="num-input1" id="dis_rm" value=""
onblur="document.getElementById('dis_per').disabled = (''!=this.value);" >
<input type="checkbox" name="num-input2" id="dis_per" value=""
onblur="document.getElementById('dis_rm').disabled = (''!=this.value);" >
If I fill in the text field, the checkbox is successfully disabled. However, if I tick the checkbox, the text field remains available.
What am I missing?

If I were you I would:
Move my JS code out of the HTML and into a separate file or at least into a script element.
Use document.getElementById to find an item in the DOM. See https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
Once you have the element from the DOM, add an event listener for the blur events like this myElement.addEventListener('blur', myCallbackMethod). See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener for more info.
Inside your callback method you can use event.target.checked to see if the element you've added the event listener to is checked.
Here is a little snippet to get you going:
const
textInput = document.getElementById('element-ID-here'),
checkbox = document.getElementById('element-ID-here');
function onTextInputBlurHandler(event) {
// if textinput value is empty then
// set disabled for checkbox to false
// else
// set disabled for chexbox to true
}
textInput.addEventListenet('blur', onTextInputBlurHandler);
<input type="text" name="num-input1" id="dis_rm" value=""/>
<input type="checkbox" name="num-input2" id="dis_per" value=""/>
With this info you should be able to get (a little) further. When you do, update your question with your JavaScript code and I am sure people will be happy to help you further.

People are bringing up great suggestions in the comments and answers for better code design and quality, but from a purely functional point of view, there are two core things that you should do to get the functionality that you are describing:
1) As mentioned by Paul S. use the checked property for your checkbox logic. Right now, you are checking to see if the checkbox value is not an empty string, but it will always be an empty string, because that's the value that you've assigned to the element:
<input type="checkbox" name="num-input2" id="dis_per" value="" <----- *here*
Nothing else in your code is changing that, so it will always fail the logic check.
However, the checked property automatically switches between true and false as you check and uncheck the input. To do the logic check that you are looking for using that, do this for your JavaScript!
document.getElementById('dis_rm').disabled = this.checked;
2) Switch the event that you are binding for (at least) the checkbox to the "change" event instead of "blur". For checkboxes, the "change" event will trigger when you click on the checkbox (or hit space bar), but the element still maintains its focus. The blur event Will only fire once the user moves the focus to another element of the page.
I'd also recommend using "change" for the text field (there's no point in running the check, if the value is the same when you leave the field as it was when you entered it), but it's not as important since, from a timing point of view, when the "change" event fires, it happens immediately after the "blur" event, so, from the user's point-of-view, the behavior would be the same.
When it's all said and done, if you made no other changes to your code to improve the code design/quality (Thijs made some great suggestions, BTW), this is the minimum change that you would need to get the functionality that you want:
<input type="text" name="num-input1" id="dis_rm" value=""
onblur="document.getElementById('dis_per').disabled = (''!=this.value);" >
<input type="checkbox" name="num-input2" id="dis_per" value=""
onchange="document.getElementById('dis_rm').disabled = (this.checked);" >

Related

(input) attribute in Angular

I can't seem to find out what (input) does in Angular. Here's the code sample:
<input class="form-control" placeholder="person" (input)="filterPersons($event.target.value, 'Hair Colour')">
I have placed a log inside the filterPersons method to see when it is executed but nothing gets outputted at all when I click/unclick the checkbox or submit the form. What functionality does (input) actually provide?
Worth noting that there are no errors and the codebase works fine and in fact there are multiple examples of this throughout the codebase so I know it's not a simple typing error but I cannot see what effect it has.
It seems like what you want is this:
https://developer.mozilla.org/de/docs/Web/HTML/Element/Input/checkbox
as the input type and then you can listen for changes via the change event instead of input (There is no input on checkbox):
<input type="checkbox" class="form-control" placeholder="person" (change)="filterPersons($event.target.value, 'Hair Colour')">
As on getting triggered on the form submit, you would have to do that programmatically or store the state when the input changes.
Try providing type="text" / type="number" and I'm sure you will see your method being executed. The (input) event fires on every key press and can be used if you want immediate validation of an input (The (change) event fires when you leave the control.)
I don't know why could not able to find what (input) actually does. In your code
<input class="form-control" placeholder="person" (input)="filterPersons($event.target.value, 'Hair Colour')">
(input) call filterPersons method with 2 parameters.
Please check the stackblitz link and see the console.log value. It changes on every single input.
StackBlitz Demo Link.

Click vs Input vs Change for checkboxes?

I have a form. I want to only allow form submit if the user checks precisely 4 out of 8 available checkboxes; and once the user checks 4 checkboxes I want to disable the remaining unchecked ones.
Should I add a hook to the click event? Or maybe the input event? Or perhaps the change event?
I'm overwhelemed by the amount of events that seem to duplicate each other's functionality.
I'm also confused by the documentation.
MDN docs about input:
For <input> elements with type=checkbox or type=radio, the input event should fire whenever a user toggles the control, per the HTML5 specification. However, historically this has not always been the case. Check compatibility, or use the change event instead for elements of these types.
MDN docs about change:
Unlike the input event, the change event is not necessarily fired for each alteration to an element's value.
And below:
Depending on the kind of element being changed and the way the user interacts with the element, the change event fires at a different moment:
When the element is :checked (by clicking or using the keyboard) for <input type="radio"> and <input type="checkbox">;
MDN docs about click:
An element receives a click event when a pointing device button (such as a mouse's primary mouse button) is both pressed and released while the pointer is located inside the element.
Practice:
The below JS fiddle seems to hint that all 3 events are equivalent. Clicking the checkbox, clicking the label, focusing the checkbox and pressing space on keyboard seem to all fire all three events.
const checkbox = document.querySelector('input[type=checkbox]');
for (const event of ['input', 'click', 'change']) {
checkbox.addEventListener(event, () => {
log.textContent = `${event}\n${log.textContent}`
})
}
<label>Toggle <input type="checkbox" name="" id="">
</label>
<pre id="log"></pre>
As per the docs change and input seem equivalent; click does not seem equivalent to the other 3 as per the docs but in practice it seems equivalent.
Do we really have 3 events that duplicate each other's functionality? Does it matter in any way which event I use?
Or am I missing something?
These 3 events duplicate each other's functionality because you are looking at a checkbox which happens to be a special case.
For example, if you were to take a text field
The event input will fire whenever the text in an element is changed using the user interface.
The event change will fire (on most browsers) whenever the text element loses focus. It would only be triggered once instead of after every keystroke.
The event click will fire whenever a user clicks on the text field.
If we were to apply this to checkboxes (keeping in mind there is only one thing a checkbox can be changes into: either checked => unchecked orunchecked => checked)
The event input will fire whenever the checked state is changed using user interface.
The event change will fire whenever the checked state has changed
in an element (or when the checkbox loses focus in IE).
The event click will fire after the check state has finished changing .
The 3 events have very similar functionality (almost duplicates) because they are all trying to do something different that functionally does the same thing on checkboxes. The only differences being subtle implementation details.
I would use click to avoid having issues from the user of diffrent browsers.
They are not duplicated. There are subtle differences.
change happens once the value or state changes, and the element loses focus.
$('input').on('change', function(){
console.log('changed');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" value="1">
<input type="text">
click happens once the element is clicked.
input happens IMMEDIATELY once the value or state changes, before it loses focus. This happens regardless of if the state changes as per a mouse or keyboard event. A checkbox can change state by clicking it, or focusing on it and hitting the spacebar. A click event would not catch the spacebar state change.
$('input').on('change', function(){
console.log('changed');
});
$('input').on('input', function(){
console.log('input');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" value="1">
<input type="text">
To test the lack of focus change and the spacebar change on the checkbox, you can click the input box and then shift+tab to focus the checkbox to hit spacebar. It appears from the fiddle that for checkboxes, the change and input events both happen any time it changes, even without the focus being lost.
This differs from how the text field behaves. So there appears to be some behavioral differences between the two elements in when the events are generated. The checkboxes appear to follow a less strict implementation of the pattern, as opposed to input boxes.

Disable checkbox by passing the value

As the title suggests, I have a form, which as soon as the user registers he is forced to compile, then the user can return to this form, and obviously the form on the screen will present the choices that the user has previously made, now to make that the checkbox is enabled if the user has previously pressed on the checkbox, I succeed with this code here, and the checkbox, appears to me on the selected screen:
<input <?php if (!(strcmp($row_mostra_tabella_email['aut_privacy'],"S"))) {echo "checked=\"checked\"";} ?> type="checkbox" id="aut_privacy" type="checkbox" value="S" name="aut_privacy" >
the problem is that if I do the same thing with the disabled command, when the user presses enter, I don't pass the command value = "s".
I would just like the checkbox to be selected and disabled, how do I do it?
As you have discovered, when you disable the element, it is not sent to the server.
There are a couple of things you could add to the element that would prevent user interaction. One is the style property pointer-events and the other is the element attribute tabindex
If the input element has style property pointer-events: none, the user cannot access it with mouse click (or touch). WARNING: If the input has a label, the label is "clickable" too, in that case, suggest wrapping both in a <div> with that style property.
That will prevent the user from directly interacting with the element, but there is always tab. Use tabindex=-1 so that the checkbox does not "participate in sequential keyboard navigation".
Having read at Dino's answer I realise what you mean (I think). The simplest way to do that is to display the checkbox as checked and disabled then add a hidden input with the correct name and value, that way the user cannot interact with the checkbox, but the value is sent back to php in the form submission. If this isn't what you mean then you do need to re-write your question

onchange isn't working

I am learning JavaScript through the Head First series book by O'Reilly media, and I just reached a chapter where I have to use the onchange event.
I'm testing using Safari/OS X Lion, Firefox, Chrome, Opera, and IE/Windows, but got the same result.
Given this code:
<html>
<head>
<title>onChange Test</title>
<script type="text/javascript">
function itWorks(){
alert("it works!");
}
</script>
</head>
<body>
<form>
<input type="text" onchange="itWorks();" />
<input type="text" onchange="itWorks();" />
</form>
</body>
<html>
Is it correct to say that the onchange event works whenever we change from one field to another, whether it is activated only by clicking or by using the TAB key?
The onchange event fires when:
Focus leaves the field
if the value has changed since focus was gained
It doesn't matter how focus was lost, and focus doesn't need to move to another field (a link could be focused, or nothing in the document could be, etc).
"we change from one field to another, whether its by clicking or by
using the TAB key" -
Thats onblur.
the event you have coded fires whenever you change the value of the input, then leave the field. EG: Enter something into the field, then press the TAB key.
Your example code works as expected for me.
The behaviors you described is onfocus. onchange executes when the value of the input changes.
If you type something into the field, it should run.
"Just to clarify, the onchange event works whenever we change from one field to another, whether its by clicking or by using the TAB key, right?"
Yes - as long as the value has changed
I'm not sure what the question is tbh - your code works!
I tested it on jsfiddle.net - which is great for learing / testing javascript.
(you should close your html tag btw)...
This is what the HTML5 draft spec says:
The unfocusing steps are as follows:
If the element is an input element, and the change event applies
to the element, and the element does not have a defined activation
behavior, and the user has changed the element's value or its list of
selected files while the control was focused without committing that
change, then fire a simple event that bubbles named change at the
element.
Unfocus the element.
Fire a simple event named blur at the element.
Note that change can fire at other times too. The spec also says:
... any time the user commits a change to the element's value or list of
selected files, the user agent must queue a task to fire a simple
event that bubbles named change at the input element.
And goes on to provide a couple of examples of "committing a change"
An example of a user interface with a commit action would be a File
Upload control that consists of a single button that brings up a file
selection dialog: when the dialog is closed, if that the file
selection changed as a result, then the user has committed a new file
selection.
Another example of a user interface with a commit action would be a
Date control that allows both text-based user input and user selection
from a drop-down calendar: while text input might not have an explicit
commit step, selecting a date from the drop down calendar and then
dismissing the drop down would be a commit action.

"SelectAll" checkbox not working when back button on the browser is clicked

I have the following html page:
<html>
<body>
<script>
var check = 0;
function doNow()
{
void(d=document);
void(el=d.getElementsByTagName('INPUT'));
for(i=0;i<el.length;i++)
{
if(check == 0)
void(el[i].checked=1)
else
void(el[i].checked=0)
}
if(check == 0)
check = 1;
else
check = 0;
}
</script>
<HR>
<form>
<INPUT TYPE="CHECKBOX" name="DG1">DG1
<INPUT TYPE="CHECKBOX" name="DG2">DG2
<INPUT TYPE="CHECKBOX" name="DG3">DG3
<INPUT TYPE="CHECKBOX" name="DG4">DG4
<INPUT TYPE="CHECKBOX" name="DG5">DG5
<input type=button onclick="doNow()" value="CheckBox All Now">
</form>
</body>
</html>
If "CheckBox All Now" is clicked all checkboxes are checked. Then,
if "Back" button or "Refresh" button is pressed. The "CheckBox All now" has to clicked twice to uncheck all checkboxes.
Please let me know how to handle "CheckBox All Now" in case of "Refresh" or "Back".
Thanks in Advance,
Mahesh.
It's because when the page is reloaded, the Javascript is parsed and your declaration
var check = 0;
unsurprisingly causes the check variable to be reset to zero at this point. Thus after the page is reinitialised, the first click of the button will enable all checkboxes. It seems that the issue here stems from a difference in how the form renderer remembers state, and how the Javascript engine remembers "state". The latter can't really be "fixed" the way you want as the script essentially needs to be run every time.
What you might choose to do is pull the initial "checked" state out of the controls themselves. Your current code explicitly assumes that the checkboxes will all be unchecked initially (this is basically what you're saying by "check = 0"; this variable is storing the state of the checkboxes as far as the Javascript is aware). Instead, you might change the line to:
var check = document.getElementsByTagName('INPUT')[0].checked;
Of course, this wouldn't work in the current location as it is declared before the form is defined. You would either need to register this as a closure to be run once the document has loaded, or alternatively pull this line out and put it in <script> tags that occur after the form element in the document (this isn't the cleanest way to do it but works for quick-and-dirty development; registration of functions within the head is the way to go in general).
I've tested both approaches and they work. I'm sure that there will be other potential solutions to this issue that come up with other peoples' answers!
EDIT: Big edit after thinking about this for a while. The fundamental issue here is that the check variable gets out-of-sync with the actual checkboxes themselves - what I described above is a way to avoid this when the page is reloaded/reinitialised.
However, you will still have other issues. What happens if the user manually clicks all of the checkboxes? They will now be active, but your check variable will still be 0, and so click the "check all" button will activate them all (which will have no effect). If I clicked this button with all checkboxes checked, I would expect it to behave consistently, regardless of how those checkboxes got to that state (which should be irrelevant).
Also, what happens if some of your checkboxes are checked and some are unchecked? What is the button meant to do in that situation?
The best solution overall would probably be to remove the check variable altogether, and instead work it out on demand at thstart of every doNow call. That is, inspect the array of checkboxes, read their current values and from this derive what the checkboxes should be set to. (This might be really simply if, for example, the functionality turns out to be that every checkbox should simply be individually inverted - it depends on the actual functional requirements.)
(Also, as a coding style issue, the part of your code that says
if(check == 0)
void(el[i].checked=1)
else
void(el[i].checked=0)
can simply be replaced by
el[i].checked = (1 - check);
and asides from the fact that we're hopefully getting rid of this variable, it ought to be a boolean rather than an integer as it only has two states.)
My suggestion is to use a checkbox instead of a button. When someone clicks on the checkbox, all other checkboxes will be set to however that checkbox is set.
So, if the "Check all" checkbox is checked, and you click it. all other checkboxes will be cleared.
Should work a bit better in the scenario you describe.
dtsazza is right - when the page is refreshed you start from scratch.
I note that the 'Check All Now' button actually toggles the checked status. How about 2 buttons (links might be better); one to check all and one to uncheck all?
You could store the checked variable in a hidden field. That way it would persist with the same longevity as the checkboxes.

Categories

Resources