I have a form field that starts out disabled and has an onClick to enable it. The onClick doesn't fire (at least in FF) nor does a simple alert(1);.
The hacky version is to show a fake form field in its place that "looks" like it's disabled (grayed out style) and onClick, hide it and show the correct field enabled, but that's ugly.
Example Code
This works:
<input type="text" id="date_end" value="blah" onClick="this.disabled=true;">
This works:
<label for="date_end_off" onClick="document.getElementById('date_end').disabled=false">Test</label>
<input type="text" id="date_end" value="blah" onClick="alert(1);" disabled>
This fails:
<input type="text" id="date_end" value="blah" onClick="alert(1);" disabled>
This fails:
<input type="text" id="date_end" value="blah" onClick="document.getElementById('date_end').disabled=false" disabled>
I came across this thread in another forum so I assume I'll have to go about it a different way.
http://www.webdeveloper.com/forum/showthread.php?t=186057
Firefox, and perhaps other browsers,
disable DOM events on form fields that
are disabled. Any event that starts at
the disabled form field is completely
canceled and does not propagate up the
DOM tree. Correct me if I'm wrong, but
if you click on the disabled button,
the source of the event is the
disabled button and the click event is
completely wiped out. The browser
literally doesn't know the button got
clicked, nor does it pass the click
event on. It's as if you are clicking
on a black hole on the web page.
Work around:
Style the date fields to look as if
they are disabled.
Make a hidden "use_date" form field
with a bit value to determine
whether to use the date fields during processing.
Add new function to onClick of the date fields which will
change the style class to appear
enabled and set the "use_date" value
to 1.
Use readonly instead of disabled
For checkboxes at least, this makes them look disabled but behave normally (tested on Google Chrome). You'll have to catch the click and prevent the default action of the event as appropriate.
Using jQuery, I attach an event handler to the parents of my input controls.
<script type="text/javascript">
$(function() {
// disable all the input boxes
$(".input").attr("disabled", true);
// add handler to re-enable input boxes on click
$("td:has(.input)").click(function() {
$(".input", this).removeAttr("disabled");
});
});
</script>
All of my input controls have the class "input" and they exist in their own table cells. If you at least wrapped your input tags in a div, then this should work without a table as well.
Citing Quirksmode.org:
"A click event on a disabled form field does not fire events in Firefox and Safari. Opera fires the mousedown and mouseup events, but not the click event. IE fires mousedown and mouseup, but not click, on the form. All these implementations are considered correct."
Quirksmode's compatibility table is great to find out more about such problems.
I recently had a very similar problem and solved it by placing the input in a div and moving the onClick to the div.
<div onClick="myEnableFunction('date_end');">
<input type="text" id="date_end" value="blah" disabled>
</div>
Enabling a disabled element on click kind of defeats the purpose of disabling, don't you think? If you really want the behavior you're describing, just style it 'disabled' and remove those styles on click.
Don't implement the logic of the onClick event in the onClick's value of the input field. That's probably why it's not working in Firefox. Instead define a function as the onClick's value. For example:
<input type="text" id="date_end" value="blah" onClick="doSomething()" disabled>
<script type="text/javascript">
function doSomething()
{
alert("button pressed");
}
</script>
It will also be worth looking into JQuery. You can use it to add or remove attributes from elements and all kinds of other stuff. For instance you can remove the disabled from the the input field by writing a function like this:
<script type="text/javascript">
function doSomething()
{
alert("button pressed");
$("#date_end").removeAttr('disabled'); //removes the disabled attribut from the
//element whose id is 'date_end'
}
</script>
OR you can add it as follows:
$("#date_end").attr('disabled','true');
The Jquery site is here
You can add a div over the input that is disabled: check it out
<div onclick="javascript:document.forma.demo1.disabled=false;" style="border:0px solid black; padding:00px;">
<input type=text name="demo1" disabled style="width:30;">
</div>
In order to enable a disabled element on the client side, lets say in response to a checkbox checked or something, I ended up having to use a combination of JS and jQuery, see below:
//enable the yes & no RB
function enable()
{
var RBNo = "rbnBusinessType";
var RBYes = "rbnBusinessType";
//jQuery approach to remove disabled from containing spans
$("#" + RBYes).parent().removeAttr('disabled');
$("#" + RBNo).parent().removeAttr('disabled');
//enable yes and no RBs
document.getElementById(RBYes).disabled = false;
document.getElementById(RBNo).disabled = false;
}
After postback then, you'll need to access the request like the following in order to get at the values of your client side enabled elements:
this._Organization.BusinessTypeHUbZoneSmall = Request.Params["rbnBusinessTypeHUbZoneSmall"] == rbnBusinessTypeHUbZoneSmallYes.ID;
Inspiration taken from:
https://stackoverflow.com/questions/6995738/asp-javascript-radiobutton-enable-disable-not-included-in-postback-ajax for more information
If you simply want to prevent the user from typing data in your field, but instead want the field to populate on an event, my hack solution was to not disable the input field at all, but instead after running my onclick or onfocus functions, to call blur() so the user can not edit the field.
Related
I am learning JavaScript and and am working on a To Do list type of application.
Idea: "Add" button is set to disabled in the HTML and only to be enabled when there is at least one character.
My code only works when there is at least 2 characters and can't workout why it doesn't detect the first character.
The other realted question is how do I set the "add" button back to disable if the input box content has been deleted.
HTML
<input id="addToListInput" onkeydown="buttonStatus()" value="" type="text"><input id="addToListButton" disabled type="submit" Value="Add to list" onClick="addToList(this)">
JS
function buttonStatus() {
var input = document.getElementById('addToListInput');
var submit= document.getElementById('addToListButton');
if (input.value.trim() ==""){
submit.disabled=true;
}else{
submit.disabled=false;
}
}
Use keyup instead. By using keydown you are detecting when the key is down, but the textbox value has not changed at that point...
<input id="addToListInput" onkeyup="buttonStatus()" value="" type="text">
onkeydown is fired before the input control is actually fired, if you use onkeyup it should work as you expect.
I have a text input field and a checkbox. The checkbox must be disabled if and only if there is input in the text field. I have a solution that works great for most scenarios:
HTML:
<input type="text" id="search" />
<input type="checkbox" id="cb" />
<label for="cb">Enabled only if no search term</label>
jQuery:
$('#search').keyup(function (e) {
var enable = $(this).val() == 0;
if (enable) {
$('#cb').removeAttr('disabled');
} else {
$('#cb').attr('disabled', 'disabled');
}
});
See it live on jsFiddle.
This works when text is typed or removed using the keyboard, and when text is pasted using the keyboard.
It fails if the user pastes text using the right-click context menu, or if the user presses the little "X" that IE adds to the input field to allow the input field to be cleared.
Question
How can I improve the code so that it also works in those scenarios? Waiting for the textbox to lose focus would provide an inferior user experience.
The Real Time Validation jQuery Plugin solves this issue. However, it does not seem to work currently with delegated events.
Implementing this requires binding events to the keyup event, and a couple other events if you want to detect text changes on cut and paste. Even if you're a JavaScript god it's tedious to keeping writing this logic over and over again. Be smart and use the ZURB text change event plugin instead.
You can use the jquery change method:
http://jsfiddle.net/WDMCX/1/
$('#search').change(function() {
if( $(this).val() === '' ){
$('#cb').attr('disabled', 'disabled');
} else {
$('#cb').removeAttr('disabled');
}
});
I'm using $('form-selector').get(0).reset() to reset form values to their original page load state.
After editing, the form will submit via $.ajax() and I'll have new "default" values on our server. The form element will still exist in the dom, and the user can submit again to update. I'd like the "default" (reset values) to reflect what's on our server (ignoring any other external updates). Is it possible to update the underlying values that form.reset() will change each form element to without a page refresh?
Cross-browser support would be nice, but since this is an internal app, Google Chrome only is sufficient.
HTML
<form>
<input type="text" value="foo" name="bar" />
<input type="submit" value="Submit" />
<Input type="reset" value="Reset" />
</form>
JAVASCRIPT
$(function(){
$('form').submit(function() {
// Omitting code that sends form values to the server
// TODO: update underlying form.reset()
// values to what's currently in each
// form element.
return false;
});
});
UPDATE
Ack! I failed to mention that I'm looking for something to handle all form element types.
i.e. input[type=text], input[type=radio], input[type=checkbox], select, textarea.
Would be especially awesome if it can handle HTML5 form elements as well...
i.e. input[type=date], input[type=number], input[email], input[url], input[type=range], input[type=color], etc.
Sorry for the confusion.
If you change attributes of the form elements directly, rather than using the .val() method, the new values will be reflected on a form reset. You'll need to treat text fields differently from radio buttons, checkboxes, etc.
$('input').attr('value', function() { return this.value });
$('textarea').prop('innerHTML', function() { return this.value });
$(':checked').attr('checked', 'checked');
$(':selected').attr('selected', 'selected');
$(':not(:checked)').removeAttr('checked');
$(':not(:selected)').removeAttr('selected');
Something like this:
$("#foo").prop("defaultValue", "bar");
As David Budiac mentioned in his comment, this doesn't work for select elements. Select elements have a separate property named defaultSelected.
More about the defaultValue property
I realize that these links go to Microsoft's site but they seem to work in pretty much all mainstream browsers.
Javascript does not know what the reset values are, so you'll have to define them either on page load or make hidden field(s) with the reset values. Then when you call reset, set them.
Let's say you have hidden fields for each field you have in your form, like text boxes (you can do similar ones for dropdowns and radio/select)
If you have 2 text fields (txtfield1 and txtfield2), you would also have hidden fields for them (called txtfield1-hdn and txtfield2-hdn respectively).
$('form-selector').get(0).reset(function() {
$('form-selector').find('input').each(function(){
$(this).val($($(this).attr('id') + '-hdn').val());
});
});
of if you have default values in the text field html then you can just do this:
<input id="Text1" type="text" value="myValue" />
$('form-selector').get(0).reset(function() {
$('form-selector').find('input').each(function(){
$(this).val($(this).attr('value'));
});
});
I have been asked to disable the "ticking" of a checkbox. I am not being asked to disable the checkbox, but to simply disable the "ticking".
In other words, a user will think that a checkbox is tickable, but it is not. Instead, clicking on the checkbox will cause a modal dialog to appear, giving the user more options to turn on or off the feature that the checkbox represents. If the options chosen in the dialog cause the feature to be turned on, then the checkbox will be ticked.
Now, the real problem is that for a split second, you can still see that the checkbox is being ticked.
I have tried an approach like this:
<input type='checkbox' onclick='return false' onkeydown='return false' />
$('input[type="checkbox"]').click(function(event) {
event.preventDefault();
alert('Break');
});
If you run this, the alert will appear, showing that the tick is visible (the alert is just there to demonstrate that it still does get ticked, in production, the alert is not there). On some users with slower machines and/or in browsers with slow renderers/javascript, users can see a very faint flicker (the flicker sometimes lasts for half a second, which is noticeable).
A tester in my team has flagged this as a defect and I am supposed to fix it. I'm not sure what else I can try to prevent the tick in the checkbox from flickering!
From my point of view it is as simple as:
$(this).prop('checked', !$(this).prop('checked'));
Works both for checked and unchecked boxes
Try
event.stopPropagation();
http://jsfiddle.net/DrKfE/3/
Best solution I've come up with:
$('input[type="checkbox"]').click(function(event) {
var $checkbox = $(this);
// Ensures this code runs AFTER the browser handles click however it wants.
setTimeout(function() {
$checkbox.removeAttr('checked');
}, 0);
event.preventDefault();
event.stopPropagation();
});
This effect can't be suppressed I fear. As soon as you click on the checkbox, the state (and rendering) is changed. Then the event handlers will be called. If you do a event.preventDefault(), the checkbox will be reset after all the handlers are executed. If your handler has a long execution time (easily testable with a modal alert()) and/or the rendering engine repaints before reseting, the box will flicker.
$('input[type="checkbox"]').click(function(event) {
this.checked = false; // reset first
event.preventDefault();
// event.stopPropagation() like in Zoltan's answer would also spare some
// handler execution time, but is no more needed here
// then do the heavy processing:
alert('Break');
});
This solution will reduce the flickering to a minimum, but can't hinder it really. See Thr4wn's and RobG's answer for how to simulate a checkbox. I would prefer the following:
<button id="settings" title="open extended settings">
<img src="default_checkbox.png" />
</button>
document.getElementById("settings").addEventListener("click", function(e) {
var img = this.getElementsByTagName("img")[0]);
openExtendedSettingsDialog(function callbackTick() {
img.src = "checked_checkbox.png";
}, function callbackUntick() {
img.src = "unchecked_checkbox.png";
});
}, false);
It is very important to use return false at the end.
Something like this:
$("#checkbox").click((e) => {
e.stopPropagation();
return false;
});
Isn't is simpler ? :
<input type="checkbox" onchange="this.checked = !this.checked">
TL:DR;
HTML api's execute before JavaScript. So you must use JavaScript to undo HTML's changes.
event.target.checked = false
WHAT is the problem?
Strictly speaking: we cannot "stop" the checkbox from being ticked. Why not? Because "being ticked" exactly means that the DOM's, HTML <input> element has a checked property value of true or false, which is immediately assigned by the HTML api
console.log(event.target.checked) // will be opposite of the previous value
So it's worth explicitly mentioning this HTML api is called before scripts. Which is intuitive and should make sense, because all JavaScript files are themselves the assignment of a <script> element's attribute src, and the ancestral relationship in the DOM tree, between your <input> in question, and the <script> element running your JavaScript, is extremely important to consider.
HOW to get our solution
The HTML assigned value has not yet been painted before we have a chance to intercept the control flow (via JS file like jQuery), so we simply re-assign the checked property to a boolean value we want: false (in your case).
So in conclusion, we CAN, in-effect, "stop" the checkbox from being checked, by simply ensuring that the checked property is false on the next render and thus, won't see any changes.
Why not simply add a class in your CSS that sets pointer-events: none;?
Something like:
<style>
input.lockedCbx { pointer-events: none; }
</style>
...
<input type="checkbox" class="lockedCbx" tabindex=-1 />
...
You need the tabindex=-1 to prevent users from tabbing into the checkbox and pressing a space bar to toggle.
Now in theory you could avoid the class and use the tabindex=-1 to control the disabling as in:
<script>
input[type="checkbox"][tabindex="-1"] { pointer-events: none; }
</script>
With CSS, you can change the image of the checkbox. See http://ryanfait.com/resources/custom-checkboxes-and-radio-buttons/ and also CSS Styling Checkboxes .
I would disable the checkbox, but replace it with an image of a working checkbox. That way the checkbox doesn't look disabled, but won't be clickable.
Wrap the checkbox with another element that somehow blocks pointer events (probably via CSS). Then, handle the wrapper's click event instead of the checkbox directly. This can be done a number of ways but here's a relatively simple example implementation:
$('input[type="checkbox"').parent('.disabled').click( function() {
// Add in whatever functionality you need here
alert('Break');
});
/* Insert an invisible element that covers the checkbox */
.disabled {
position: relative;
}
.disabled::after {
content: "";
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Only wrapped checkboxes are "disabled" -->
<input type="checkbox" />
<span class="disabled"><input type="checkbox" /></span>
<input type="checkbox" />
<span class="disabled"><input type="checkbox" /></span>
<span class="disabled"><input type="checkbox" /></span>
<input type="checkbox" />
Note: You could also add the wrapper elements programmatically, if you would like.
Sounds to me like you are using the wrong interface element, a more suitable one would be a button that is disabled by default, but enabled when that option is available. The image displayed can be whatever you want.
<button disabled onclick="doSomething();">Some option</button>
When users have selected that feature, enable the button. The image on the button can be modified by CSS depending on whether it's enabled or not, or by the enable/disable function.
e.g.
<script type="text/javascript">
function setOption(el) {
var idMap = {option1:'b0', option2: 'b1'};
document.getElementById(idMap[el.value]).disabled = !el.checked;
}
</script>
<div><p>Select options</p>
<input type="checkbox" onclick="setOption(this);" value="option1"> Option 1
<br>
<input type="checkbox" onclick="setOption(this);" value="option2"> Option 2
<br>
</div>
<div>
<button id="b0" onclick="alert('Select…');" disabled>Option 1 settings</button>
<button id="b1" onclick="alert('Select…');" disabled>Option 2 settings</button>
</div>
The Event.preventDefault method should work for change, keydown, and mousedown events, but doesn't in my testing.
My solution to this problem in a Mozilla Firefox 53.0 extension was to toggle an HTML class that enabled/disabled the CSS declaration pointer-events: none being applied to the checkbox. This addresses the cursor-based case, but not the key-based case. See https://www.w3.org/TR/SVG2/interact.html#PointerEventsProp.
I addressed the key-based case by adding/removing an HTML tabindex="-1" attribute. See https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex.
Note that disabling pointer-events will disable your ability to trigger CSS cursors on hover (e.g., cursor: not-allowed). My checkbox was already wrapped in a span element, so I added an HTML class to that span element which I then retargeted my CSS cursor declaration onto.
Also note that adding a tabindex="-1" attribute will not remove focus from the checkbox, so one will need to explicitly defocus it by using the HTMLElement.blur() method or by focusing another element to prevent key-based input if the checkbox is the active element at the time the attribute is added. Whether or not the checkbox is the focused element can be tested with my_checkbox.isEqualNode(document.activeElement).
Simply revert the value back
$('input[type="checkbox"]').on('change', function(e) {
if (new Date().getDate() === 13) {
$(this).prop('checked', !$(this).prop('checked'));
e.preventDefault();
return false;
}
// some code here
});
Add this to click event in js file
event.stopPropagation();
$('#term-input').on('change click',function (e){
e.preventDefault();
})
works for me
I am trying to do some experiment. What I want to happen is that everytime the user types in something in the textbox, it will be displayed in a dialog box. I used the onchange event property to make it happen but it doesn't work. I still need to press the submit button to make it work. I read about AJAX and I am thinking to learn about this. Do I still need AJAX to make it work or is simple JavaScript enough? Please help.
index.php
<script type="text/javascript" src="javascript.js"> </script>
<form action="index.php" method="get">
Integer 1: <input type="text" id="num1" name="num1" onchange="checkInput('num1');" /> <br />
Integer 2: <input type="text" id="num2" name="num2" onchange="checkInput('num2');" /> <br />
<input type="submit" value="Compute" />
</form>
javascript.js
function checkInput(textbox) {
var textInput = document.getElementById(textbox).value;
alert(textInput);
}
onchange is only triggered when the control is blurred. Try onkeypress instead.
Use .on('input'... to monitor every change to an input (paste, keyup, etc) from jQuery 1.7 and above.
For static and dynamic inputs:
$(document).on('input', '.my-class', function(){
alert('Input changed');
});
For static inputs only:
$('.my-class').on('input', function(){
alert('Input changed');
});
JSFiddle with static/dynamic example: https://jsfiddle.net/op0zqrgy/7/
HTML5 defines an oninput event to catch all direct changes. it works for me.
Checking for keystrokes is only a partial solution, because it's possible to change the contents of an input field using mouse clicks. If you right-click into a text field you'll have cut and paste options that you can use to change the value without making a keystroke. Likewise, if autocomplete is enabled then you can left-click into a field and get a dropdown of previously entered text, and you can select from among your choices using a mouse click. Keystroke trapping will not detect either of these types of changes.
Sadly, there is no "onchange" event that reports changes immediately, at least as far as I know. But there is a solution that works for all cases: set up a timing event using setInterval().
Let's say that your input field has an id and name of "city":
<input type="text" name="city" id="city" />
Have a global variable named "city":
var city = "";
Add this to your page initialization:
setInterval(lookForCityChange, 100);
Then define a lookForCityChange() function:
function lookForCityChange()
{
var newCity = document.getElementById("city").value;
if (newCity != city) {
city = newCity;
doSomething(city); // do whatever you need to do
}
}
In this example, the value of "city" is checked every 100 milliseconds, which you can adjust according to your needs. If you like, use an anonymous function instead of defining lookForCityChange(). Be aware that your code or even the browser might provide an initial value for the input field so you might be notified of a "change" before the user does anything; adjust your code as necessary.
If the idea of a timing event going off every tenth of a second seems ungainly, you can initiate the timer when the input field receives the focus and terminate it (with clearInterval()) upon a blur. I don't think it's possible to change the value of an input field without its receiving the focus, so turning the timer on and off in this fashion should be safe.
onchange only occurs when the change to the input element is committed by the user, most of the time this is when the element loses focus.
if you want your function to fire everytime the element value changes you should use the oninput event - this is better than the key up/down events as the value can be changed with the user's mouse ie pasted in, or auto-fill etc
Read more about the change event here
Read more about the input event here
use following events instead of "onchange"
- onkeyup(event)
- onkeydown(event)
- onkeypress(event)
Firstly, what 'doesn't work'? Do you not see the alert?
Also, Your code could be simplified to this
<input type="text" id="num1" name="num1" onkeydown="checkInput(this);" /> <br />
function checkInput(obj) {
alert(obj.value);
}
I encountered issues where Safari wasn't firing "onchange" events on a text input field. I used a jQuery 1.7.2 "change" event and it didn't work either. I ended up using ZURB's textchange event. It works with mouseevents and can fire without leaving the field:
http://www.zurb.com/playground/jquery-text-change-custom-event
$('.inputClassToBind').bind('textchange', function (event, previousText) {
alert($(this).attr('id'));
});
A couple of comments that IMO are important:
input elements not not emitting 'change' event until USER action ENTER or blur await IS the correct behavior.
The event you want to use is "input" ("oninput"). Here is well demonstrated the different between the two: https://javascript.info/events-change-input
The two events signal two different user gestures/moments ("input" event means user is writing or navigating a select list options, but still didn't confirm the change. "change" means user did changed the value (with an enter or blur our)
Listening for key events like many here recommended is a bad practice in this case. (like people modifying the default behavior of ENTER on inputs)...
jQuery has nothing to do with this. This is all in HTML standard.
If you have problems understanding WHY this is the correct behavior, perhaps is helpful, as experiment, use your text editor or browser without a mouse/pad, just a keyboard.
My two cents.
onkeyup worked for me. onkeypress doesn't trigger when pressing back space.
It is better to use onchange(event) with <select>.
With <input> you can use below event:
- onkeyup(event)
- onkeydown(event)
- onkeypress(event)
when we use onchange while you are typing in input field – there’s no event. But when you move the focus somewhere else, for instance, click on a button – there will be a change event
you can use oninput
The oninput event triggers every time after a value is modified by the user.Unlike keyboard events, it triggers on any value change, even those that does not involve keyboard actions: pasting with a mouse or using speech recognition to dictate the text.
<input type="text" id="input"> oninput: <span id="result"></span>
<script>
input.oninput = function() {
console.log(input.value);
};
</script>
If we want to handle every modification of an <input> then this event is the best choice.
I have been facing the same issue until I figured out how to do it. You can utilize a React hook, useEffect, to write a JS function that will trigger after React rendering.
useEffect(()=>{
document.title='fix onChange with onkeyup';
const box = document.getElementById('changeBox');
box.onkeyup = function () {
console.log(box.value);
}
},[]);
Note onchange is not fired when the value of an input is changed. It is only changed when the input’s value is changed and then the input is blurred. What you’ll need to do is capture the keypress event when fired in the given input and that's why we have used onkeyup menthod.
In the functional component where you have the <Input/> for the <form/>write this
<form onSubmit={handleLogin} method='POST'>
<input
aria-label= 'Enter Email Address'
type='text'
placeholder='Email Address'
className='text-sm text-gray-base w-full mr-3 py-5 px-4 h-2 border border-gray-primary rounded mb-2'
id='changeBox'
/>
</form>
Resulting Image :
Console Image
try onpropertychange.
it only works for IE.