How to prevent a browser from storing passwords - html
I need to stop browsers from storing the username & password values, because I'm working on a web application which contains more secure data. My client asked me to do this.
I tried the autocomplete="off" attribute in the HTML form and password fields. But it is not working in the latest browsers like Chrome 55, Firefox 38+, Internet Explorer 11, etc.
What is the best solution for this?
Thank you for giving a reply to me. I followed the below link
Disable browser 'Save Password' functionality
I resolved the issue by just adding readonly & onfocus="this.removeAttribute('readonly');" attributes besides autocomplete="off" to the inputs as shown below.
<input type="text" name="UserName" autocomplete="off" readonly
onfocus="this.removeAttribute('readonly');" >
<input type="password" name="Password" autocomplete="off" readonly
onfocus="this.removeAttribute('readonly');" >
This is working fine for me.
Trying to prevent the browser from storing passwords is not a recommended thing to do. There are some workarounds that can do it, but modern browsers do not provide this feature out-of-the-box and for good reason. Modern browsers store passwords in password managers in order to enable users to use stronger passwords than they would usually.
As explained by MDN: How to Turn Off Form Autocompletion:
Modern browsers implement integrated password management: when the user enters a username and password for a site, the browser offers to remember it for the user. When the user visits the site again, the browser autofills the login fields with the stored values.
Additionally, the browser enables the user to choose a master password that the browser will use to encrypt stored login details.
Even without a master password, in-browser password management is generally seen as a net gain for security. Since users do not have to remember passwords that the browser stores for them, they are able to choose stronger passwords than they would otherwise.
For this reason, many modern browsers do not support autocomplete="off" for login fields:
If a site sets autocomplete="off" for a form, and the form includes username and password input fields, then the browser will still offer to remember this login, and if the user agrees, the browser will autofill those fields the next time the user visits the page.
If a site sets autocomplete="off" for username and password input fields, then the browser will still offer to remember this login, and if the user agrees, the browser will autofill those fields the next time the user visits the page.
This is the behavior in Firefox (since version 38), Google Chrome (since 34), and Internet Explorer (since version 11).
If an author would like to prevent the autofilling of password fields in user management pages where a user can specify a new password for someone other than themself, autocomplete="new-password" should be specified, though support for this has not been implemented in all browsers yet.
Here is a pure HTML/CSS solution for Chrome tested in version 65.0.3325.162 (official build) (64-bit).
Set the input type="text" and use CSS text-security:disc to mimic type="password".
<input type="text" name="username">
<input type="text" name="password" style="text-security:disc; -webkit-text-security:disc;">
Note: Works in Firefox but CSS moz-text-security is
Deprecated/Removed. To fix this create a CSS font-face made only of
dots and use font-family: 'dotsfont';.
Source:
Get input type=text to look like type=password
The Source above contains a link to a work-around for CSS moz-text-security and -webkit-text-security property.
Source: https://github.com/kylewelsby/dotsfont
As far as I have tested this solution works for Chrome, Firefox version 59.0 (64-bit), Internet Explorer version 11.0.9600 as well as the IE Emulators Internet Explorer 5 and greater.
I solved this by adding autocomplete="one-time-code" to the password input.
As per an HTML reference autocomplete="one-time-code" - a one-time code used for verifying user identity. It looks like the best fit for this.
You should be able to make a fake hidden password box to prevent it.
<form>
<div style="display:none">
<input type="password" tabindex="-1"/>
</div>
<input type="text" name="username" placeholder="username"/>
<input type="password" name="password" placeholder="password"/>
</form>
By default, there is not any proper answer to disable saving a password in your browser. But luckily there is a way around and it works in almost all the browsers.
To achieve this, add a dummy input just before the actual input with autocomplete="off" and some custom styling to hide it and providing tabIndex.
Some browsers' (Chrome) autocomplete will fill in the first password input it finds, and the input before that, so with this trick it will only fill in an invisible input that doesn't matter.
<div className="password-input">
<input
type="password"
id="prevent_autofill"
autoComplete="off"
style={{
opacity: '0',
position: 'absolute',
height: '0',
width: '0',
padding: '0',
margin: '0'
}}
tabIndex="-2"
/>
<input
type="password"
autoComplete="off"
className="password-input-box"
placeholder="Password"
onChange={e => this.handleChange(e, 'password')}
/>
</div>
I tested the many solutions and finally I came with this solution.
HTML Code
<input type="text" name="UserName" id="UserName" placeholder="UserName" autocomplete="off" />
<input type="text" name="Password" id="Password" placeholder="Password" autocomplete="off"/>
CSS Code
#Password {
text-security: disc;
-webkit-text-security: disc;
-moz-text-security: disc;
}
JavaScript Code
window.onload = function () {
init();
}
function init() {
var x = document.getElementsByTagName("input")["Password"];
var style = window.getComputedStyle(x);
console.log(style);
if (style.webkitTextSecurity) {
// Do nothing
} else {
x.setAttribute("type", "password");
}
}
At the time this was posted, neither of the previous answers worked for me.
This approach uses a visible password field to capture the password from the user and a hidden password field to pass the password to the server. The visible password field is blanked before the form is submitted, but not with a form submit event handler (see explanation on the next paragraph). This approach transfers the visible password field value to the hidden password field as soon as possible (without unnecessary overhead) and then wipes out the visible password field. If the user tabs back into the visible password field, the value is restored. It uses the placeholder to display ●●● after the field was wiped out.
I tried clearing the visible password field on the form onsubmit event, but the browser seems to be inspecting the values before the event handler and prompts the user to save the password. Actually, if the alert at the end of passwordchange is uncommented, the browser still prompts to save the password.
function formsubmit(e) {
document.getElementById('form_password').setAttribute('placeholder', 'password');
}
function userinputfocus(e) {
//Just to make the browser mark the username field as required
// like the password field does.
e.target.value = e.target.value;
}
function passwordfocus(e) {
e.target.setAttribute('placeholder', 'password');
e.target.setAttribute('required', 'required');
e.target.value = document.getElementById('password').value;
}
function passwordkeydown(e) {
if (e.key === 'Enter') {
passwordchange(e.target);
}
}
function passwordblur(e) {
passwordchange(e.target);
if (document.getElementById('password').value !== '') {
var placeholder = '';
for (i = 0; i < document.getElementById('password').value.length; i++) {
placeholder = placeholder + '●';
}
document.getElementById('form_password').setAttribute('placeholder', placeholder);
} else {
document.getElementById('form_password').setAttribute('placeholder', 'password');
}
}
function passwordchange(password) {
if (password.getAttribute('placeholder') === 'password') {
if (password.value === '') {
password.setAttribute('required', 'required');
} else {
password.removeAttribute('required');
var placeholder = '';
for (i = 0; i < password.value.length; i++) {
placeholder = placeholder + '●';
}
}
document.getElementById('password').value = password.value;
password.value = '';
//This alert will make the browser prompt for a password save
//alert(e.type);
}
}
#form_password:not([placeholder='password'])::placeholder {
color: red; /*change to black*/
opacity: 1;
}
<form onsubmit="formsubmit(event)" action="/action_page.php">
<input type="hidden" id="password" name="password" />
<input type="text" id="username" name="username" required
autocomplete="off" placeholder="username"
onfocus="userinputfocus(event)" />
<input type="password" id="form_password" name="form_password" required
autocomplete="off" placeholder="password"
onfocus="passwordfocus(event)"
onkeydown="passwordkeydown(event)"
onblur="passwordblur(event)"/>
<br />
<input type="submit"/>
< input type="password" style='pointer-event: none' onInput= (e) => handleInput(e) />
function handleInput(e) {
e.preventDefault();
e.stopPropagation();
e.target.setAttribute('readonly', true);
setTimeout(() => {
e.target.focus();
e.target.removeAttribute('readonly');
});
}
I'm making a PWA using React. (And using Material-UI and Formik on the component in question, so syntax may seem a bit unusual...)
I wanted to stop Chrome from trying to save login credentials (because devices are shared with many users in my situation).
For the input (MUI TextField in my case), I set the type to "text" rather than "password" in order to get around Chromes detection for the store-credentials-feature. I made input-mode as "numeric" to get the keypad to pop up as the keyboard, because users will input a PIN for their password.
And then, as others here described, I used text-security: disc; and -webkit-text-security: disc;
Again, careful of my code's syntax, as it's using React, MUI, etc. (React uses capital letters and no dashes, etc.)
See the parts with the // comment; the rest is just bonus for context.
<TextField
type="text" // this is a hack so Chrome does not offer saved credentials; should be "password" otherwise
name="pincode"
placeholder="pin"
value={values[PIN_FIELD]}
onChange={handleChange}
onBlur={handleBlur}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<RemoveRedEye
color="action"
onClick={togglePasswordMask}
/>
</InputAdornment>
),
inputProps: {
inputMode: 'numeric', // for number keyboard
style: {
textSecurity: `${passwordIsMasked ? 'disc' : ''} `, // part of hack described above. this disc mimics the password *** appearance
WebkitTextSecurity: `${passwordIsMasked ? 'disc' : ''} `, // same hack
},
},
}}
/>
As you can see, I have a toggle that lets you hide or show the pin (by clicking the eye icon). A similar function could be added as appropriate / desired.
const [passwordIsMasked, setPasswordIsMasked] = useState(true)
const togglePasswordMask = () => {
setPasswordIsMasked((value) => !value)
}
Here's a pure html/css (no js) solution
For input/type=text, use a textarea
For password, use a textarea with a circle glyph font (see https://stackoverflow.com/a/40982531/146457)
<textarea required="required" autocorrect="off" autocapitalize="off" name="username" class="form-control" placeholder="Your username" rows="1" cols="20" wrap="off"></textarea>
<textarea required="required" autocorrect="off" autocapitalize="off" name="password" class="form-control password" placeholder="Your password" rows="1" cols="20" wrap="off"></textarea>
#font-face {
font-family: 'password';
src: url('css/font/password.woff2') format('woff2'),
url('css/font/password.woff') format('woff'),
url('css/font/password.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
textarea.form-control {
overflow:hidden;
resize:none;
height:34px;
}
textarea.form-control.password:valid {
font-family: 'password';
}
Notes
Textarea prevent autofill & password manager trigger
wrap=off/overlow=hidden/rows=1 force one-line display
the required pseudo css make the placeholder works
You'll probably need some "prevent eventKey=13 / submit" thing
Works fine under ffox/chrome/iOS
In the end, it end up been a freaking webshit sum of hacks (but it works)
This worked for me:
<form action='/login' class='login-form' autocomplete='off'>
User:
<input type='user' name='user-entry'>
<input type='hidden' name='user'>
Password:
<input type='password' name='password-entry'>
<input type='hidden' name='password'>
</form>
I think it is not possible in the latest browsers.
The only way you can do that is to take another hidden password field and use it for your logic after taking value from visible password field while submitting and put dummy string in visible password field.
In this case the browser can store a dummy string instead of the actual password.
Try the following. It may be help you.
For more information, visit Input type=password, don't let browser remember the password
function setAutoCompleteOFF(tm) {
if(typeof tm == "undefined") {
tm = 10;
}
try {
var inputs = $(".auto-complete-off, input[autocomplete=off]");
setTimeout(function() {
inputs.each(function() {
var old_value = $(this).attr("value");
var thisobj = $(this);
setTimeout(function() {
thisobj.removeClass("auto-complete-off").addClass("auto-complete-off-processed");
thisobj.val(old_value);
}, tm);
});
}, tm);
}
catch(e){
}
}
$(function(){
setAutoCompleteOFF();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="passfld" type="password" autocomplete="off" />
<input type="submit">
One way would be to generate random input names and work with them.
This way, browsers will be presented with the new form each time and won't be able to pre-populate the input fields.
If you provide us with some sample code (do you have a JavaScript single-page application (SPA) app or some server side rendering) I would be happy to help you in the implementation.
I needed this a couple of years ago for a specific situation: Two people who know their network passwords access the same machine at the same time to sign a legal agreement.
You don't want either password saved in that situation because saving a password is a legal issue, not a technical one where both the physical and temporal presence of both individuals is mandatory. Now, I'll agree that this is a rare situation to encounter, but such situations do exist and built-in password managers in web browsers are unhelpful.
My technical solution to the above was to swap between password and text types and make the background color match the text color when the field is a plain text field (thereby continuing to hide the password). Browsers don't ask to save passwords that are stored in plain text fields.
jQuery plugin:
https://github.com/cubiclesoft/php-flexforms-modules/blob/master/password-manager/jquery.stoppasswordmanager.js
Relevant source code from the above link:
(function($) {
$.fn.StopPasswordManager = function() {
return this.each(function() {
var $this = $(this);
$this.addClass('no-print');
$this.attr('data-background-color', $this.css('background-color'));
$this.css('background-color', $this.css('color'));
$this.attr('type', 'text');
$this.attr('autocomplete', 'off');
$this.focus(function() {
$this.attr('type', 'password');
$this.css('background-color', $this.attr('data-background-color'));
});
$this.blur(function() {
$this.css('background-color', $this.css('color'));
$this.attr('type', 'text');
$this[0].selectionStart = $this[0].selectionEnd;
});
$this.on('keydown', function(e) {
if (e.keyCode == 13)
{
$this.css('background-color', $this.css('color'));
$this.attr('type', 'text');
$this[0].selectionStart = $this[0].selectionEnd;
}
});
});
}
}(jQuery));
Demo:
https://barebonescms.com/demos/admin_pack/admin.php
Click "Add Entry" in the menu and then scroll to the bottom of the page to "Module: Stop Password Manager".
One thing you can do is ask your users to disable saving the password for your site. This can be done browser wide or origin wide.
Something else you can do is to force the inputs to be empty after the page is loaded (and after the browser auto completed the fields). Put this script at the end of the <body> element.
userIdInputElement.value = "";
userPasswordInputElement.value = "";
I would create a session variable and randomize it. Then build the id and name values based on the session variable. Then on login interrogate the session var you created.
if (!isset($_SESSION['autoMaskPassword'])) {
$bytes = random_bytes(16);
$_SESSION['autoMask_password'] = bin2hex($bytes);
}
<input type="password" name="<?=$_SESSION['autoMaskPassword']?>" placeholder="password">
In such a situation, I populate the password field with some random characters just after the original password is retrieved by the internal JavaScript code, but just before the form submission.
NOTE: The actual password is surely used for the next step by the form. The value is transferred to a hidden field first. See the code example.
That way, when the browser's password manager saves the password, it is not really the password the user had given there. So the user thinks the password has been saved, when in fact some random stuff is what got saved. Over time, the user would know that he/she can't trust the password manager to do the right job for that site.
Now this can lead to a bad user experience; I know because the user may feel that the browser has indeed saved the password. But with adequate documentation, the user can be consoled. I feel this is the way one can fully be sure that the actual password entered by the user cannot be picked up by the browser and saved.
<form id='frm' action="https://google.com">
Password: <input type="password" id="pwd" />
<input type='hidden' id='hiddenpwd' />
<button onclick='subm()'>Submit this</button>
</form>
<script>
function subm() {
var actualpwd = $('#pwd').val();
$('#hiddenpwd').val(actualpwd);
// ...Do whatever Ajax, etc. with this actual pwd
// ...Or assign the value to another hidden field
$('#pwd').val('globbedygook');
$('#frm').submit();
}
</script>
I did it by setting the input field as "text", and catching and manipulating the input keys
first activate a function to catch keys
yourInputElement.addEventListener('keydown', onInputPassword);
the onInputPassword function is like this:
(assuming that you have the "password" variable defined somewhere)
onInputPassword( event ) {
let key = event.key;
event.preventDefault(); // this is to prevent the key to reach the input field
if( key == "Enter" ) {
// here you put a call to the function that will do something with the password
}
else if( key == "Backspace" ) {
if( password ) {
// remove the last character if any
yourInputElement.value = yourInputElement.value.slice(0, -1);
password = password.slice(0, -1);
}
}
else if( (key >= '0' && key <= '9') || (key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z') ) {
// show a fake '*' on input field and store the real password
yourInputElement.value = yourInputElement.value + "*";
password += key;
}
}
so all alphanumeric keys will be added to the password, the 'backspace' key will erase one character, the 'enter' key will terminate, and any other keys will be ignored
don't forget to call removeEventListener('keydown', onInputPassword) somewhere at the end
While the previous solutions are very correct, if you absolutely need the feature then you can mimic the situation with custom input using text-field and JavaScript.
For secure usage, you can use any cryptography technique. So this way you will bypass the browser's password saving behavior.
If you want to know more about the idea, we can discuss that on chat. But the gist is discussed in previous answers and you can get the idea.
It is working fine for a password field to prevent to remember its history:
$('#multi_user_timeout_pin').on('input keydown', function(e) {
if (e.keyCode == 8 && $(this).val().length == 1) {
$(this).attr('type', 'text');
$(this).val('');
} else {
if ($(this).val() !== '') {
$(this).attr('type', 'password');
} else {
$(this).attr('type', 'text');
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="multi_user_timeout_pin" name="multi_user_pin" autocomplete="off" class="form-control" placeholder="Type your PIN here" ng-model="logutUserPin">
I just change the type attribute of the field password to hidden before the click event:
document.getElementById("password").setAttribute("type", "hidden");
document.getElementById("save").click();
The password input box is essentially character replacement.
1.download font https://pan.baidu.com/s/1TnlCRB8cam6KgS6OarXu3w (c23n)
2.
<style>
#font-face {
font-family: 'htmlpassword';
font-style: normal;
font-weight: 300;
src: url(./css/fonts/htmlpassword.woff2) format('woff2');
}
</style>
<input type="text" autocomplete="off" name="password" style="font-family: "htmlpassword";">
Try
<input type="password" placeholder="Enter password" autocomplete="new-password">
autocomplete="new-password" works for me.
Related
Why doesn't the autocapitalize attribute work with non-virtual keyboards?
I just found that we can use this attribute to specify which case the letters should be entered in, but that doesn't work for me. Example: <input type="text" autocapitalize="words" name="subject" value="Website Feedback" /> I set this attr to words but still type with lover case each new word, so how it should work?
As many in the comments have pointed out, the attribute does not affect phisical keyboards. You can achieve this using javascript, by listening to the keyup event and capitalizing the text every time it changes. Here is a working example: $(".autocapitalize").keyup(function () { const originalValue = $(this).val(); const capitalizedValue = originalValue.replace(/(^\w{1})|(\s+\w{1})/g, letter => letter.toUpperCase()); $(this).val(capitalizedValue).focus() }); <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <input type="text" class="autocapitalize" autocapitalize="words" name="subject" value="" />
It seems that some browsers do not take this attribute into account more "autocapitalize attribute doesn't affect behavior when typing on a physical keyboard". https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocapitalize Maybe you should use a function instead.
HTML 5 Input type='date' disable keyboard input
I am working on a Chrome Packaged App so my code should only work in Chrome. I have the following input <input type="date" /> https://jsfiddle.net/jhbo4q2k/ On Chrome this automatically adds a DatePicker. I would like to only keep this Datepicker and disable the input by keyboard. Is this possible? EDIT: The accepted answer works. Just be wary of this https://developer.chrome.com/extensions/tut_migration_to_manifest_v2#inline_scripts You cant use inline scripts in a packaged app.
You can use onkeydown and prevent user from entering the value. <input type="date" onkeydown="return false" />
For ReactJS above solutions don't work I had to do: <input type="date" onKeyDown={(e) => e.preventDefault()} .... />
Hi you can prevent keyboard popup by using onfocus="blur()". Since when the element has the focus we will remove the focus out of it(native keyboards won't show) however with onclick we can continue with our operations. <input type="date" class="form-control" onfocus="blur()" onclick="dosomework()" name="some-name" id="some-id" > <script> function dosomework(){ alert('hi'); } <script>
If using django forms; datetime = forms.DateTimeField(widget=forms.DateTimeInput(attrs={ 'onkeydown': 'return false' # If you want to disable the keyboard "onfocus": 'blur()' # If you also want to disable virtual keyboard(on smartphones). })) OR document.getElementById('id_datetime').onkeydown = (e) => { e.preventDefault(); } document.getElementById('id_datetime').setAttribute('onfocus', 'blur()'); Django simply adds 'id' in front of the input field name and sets that as its id. Here the input field name is datetime, so the id will be id_datetime.
Easy Way To Enable & Disable Input Date: Step 1: create input date. <input type="date" id="dateEnd"> Step 2: create enable and disable button <button onclick="disableBtn()">Disable Date Field</button> <button onclick="undisableBtn()">Undisable Date Field</button> Step 3: Javascript for enabling and disabling <script> function disableBtn() { document.getElementById("dateEnd").disabled = true; } function undisableBtn() { document.getElementById("dateEnd").disabled = false; } </script> Hope, this may help you.
e.preventDefault() will do the job... const inputDate = document.querySelector("input"); inputDate.addEventListener("keydown", function (e) { e.preventDefault(); }); <input type="date">
Disabling keyboard input is a great way to make your application less accessible to people with disabilities and make it less user friendly in general, in my opinion keyboard input is much easier to use than date pickers, especially if the expected format is clear. You'd be better off doing some basic field validation to ensure that the input is sensible before letting it be submitted, the HTML date field already has strong validation on it by default on Chrome Firefox and Edge.
Html placeholder text in a textarea form
On one of my websites I have created a form that collects the persons name, email and a description of their idea. I limited the characters of the description to 500 characters as I don't want to read a ton and I figured out how to have the text appear in the textarea before the user inputs what they want. Currently the user has to delete "Description of your idea" themselves but I want to add the placeholder class where it deletes what I have written in the textarea when they click the textarea I have looked on a few sites and couldn't figure out how to use it I placed it in my code, but usually the class just appeared as text inside my textarea. Any help on using this class would be great thank you Here is what I have written Inside the head tags <script language="javascript" type="text/javascript"> function limitText(limitField, limitCount, limitNum) { if (limitField.value.length > limitNum) { limitField.value = limitField.value.substring(0, limitNum); } else { limitCount.value = limitNum - limitField.value.length; } } </script> Inside the body tags <form name="form1" method="post" action="ideas.php"> Your Name: <input type="text" name="name"><br> Your Email: <input type="text" name="email"<br> <textarea name="desc" cols=50 rows=10 onKeyDown="limitText(this.form.desc,this.form.countdown,500);" onKeyUp="limitText(this.form.desc,this.form.countdown,500);">Description of your idea</textarea><br> <font size="1">(Maximum characters: 500)<br> You have <input readonly type="text" name="countdown" size="3" value="500"> characters left.</font> <br> <input type="submit" name="Submit" value="Submit!"> </form>
There is a feature in HTML5 called 'placeholders', which produces exactly this feature without you having to do any coding at all. All you need to do is add a placeholder attribute to your form field, like so: <input type='text' name='name' placeholder='Enter your name'> Sadly, of course, only a few browsers currently support it, but give it a go in Safari or Chrome to see it in action. The good news is that it is being added to virtually all browsers in the near future. Of course, you still need to cater for users with older browsers, but you may as well make use of the feature in browsers that can use it. A good way to deal with it is to use the placeholder attribute, and only fall back to the Javascript solution if the browser doesn't support the feature. The Javascript solution can take the text from the placeholder attribute, so you only need to specify it in one place. See this page for how to detect whether the placeholder feature is supported: http://diveintohtml5.ep.io/detect.html (or, as it says on that page, just use Modernizr) The Javascript fall-back code is fairly simple to implement. Exactly how you do it would depend on whether you want to use JQuery or not, but here are links to a few examples: http://www.morethannothing.co.uk/2010/01/placeholder-text-in-html5-a-js-fallback/ http://www.hagenburger.net/BLOG/HTML5-Input-Placeholder-Fix-With-jQuery.html And of course Google will give you loads more if you search for html5 placeholder fallback or something similar. Hope that helps.
Check out http://www.ajaxblender.com/howto-add-hints-form-auto-focus-using-javascript.html I think it has what you are looking for. Here is a simple page that has an email field on it that I quickly put together (pulled mostly from the tutorial). <html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.1.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ // Focus auto-focus fields $('.auto-focus:first').focus(); // Initialize auto-hint fields $('INPUT.auto-hint, TEXTAREA.auto-hint').focus(function(){ if($(this).val() == $(this).attr('title')){ $(this).val(''); $(this).removeClass('auto-hint'); } }); $('INPUT.auto-hint, TEXTAREA.auto-hint').blur(function(){ if($(this).val() == '' && $(this).attr('title') != ''){ $(this).val($(this).attr('title')); $(this).addClass('auto-hint'); } }); $('INPUT.auto-hint, TEXTAREA.auto-hint').each(function(){ if($(this).attr('title') == ''){ return; } if($(this).val() == ''){ $(this).val($(this).attr('title')); } else { $(this).removeClass('auto-hint'); } }); }); </script> </head> <body> <form> Email: <input type="text" name="email" id="email" title="i.e. me#example.com" class="auto-hint" /> </form> </body> </html> The title text is put in the field if it's empty, and removed once the user starts typing.
IE8/Firefox Behavioral Difference
I'm working on login page written as a JSP. It's pretty simple but behaves differently in IE8 and Firefox (big surprise there). I have not tested this is other browsers yet. I could probably hack a fix in with some Javascript but I was looking for more information about the behavior, before I just implement a workaround, with hopes of a cleaner fix and avoiding this problem in the future. The server-side generated HTML snippet in question is this: <form name="member_session_info" method="post" autocomplete="off" action="/membersession" onsubmit="return validate_form()" > <input type="hidden" id="memberSessionAction" name="memberSessionAction" value="" /> <input type="hidden" name="homePage" value="/2009/aas/aas_home.jsp" /> <input type="hidden" name="memberLandingPage" value="/2009/aas/aas_member_landing.jsp" /> <input type="hidden" name="memberProfilePage" value="/2009/aas/aas_member_profile.jsp" /> <input type="hidden" name="passwordRecoveryPage" value="/2009/aas/aas_password_recovery.jsp" /> <input id="uname" class="text xsmall right" name="username" value="USERNAME" onclick="checkClickUser()" onKeyPress="checkKeyPress(event, 'login', sendProfile)" style="width: 220px;" type="text"> <input id="pass" class="text xsmall right" name="password" value="PASSWORD" onclick="checkClickPassword()" onKeyPress="checkKeyPress(event, 'login', sendProfile)" style="width: 220px;" type="password"> FORGOT PASSWORD </form> and the Javascript that backs it up is: <script type="text/javascript" language="JavaScript"> function validatePost(code, doAlert) { postValid = true; return postValid; } function sendProfile(action) { document.getElementById("memberSessionAction").value = action; document.member_session_info.submit(); return false; } function initializePage() { } function validate_form() { return false; } function checkClickUser() { var username; username = document.getElementById("uname").value; if (username == "USERNAME") { // Clear the field since it's the first time document.getElementById("uname").value = ""; } return true; } function checkClickPassword() { var username; username = document.getElementById("pass").value; if (username == "PASSWORD") { // Clear the field since it's the first time document.getElementById("pass").value = ""; } return true; } function checkKeyPress(event, object, func) { var keycode; if (window.event) keycode = window.event.keyCode; else if (event) keycode = (event.which) ? event.which : event.keyCode; else return true; if ((keycode == 13)) // check for return { func(object); return true; } return true; } </script> The basic symptom is this: If you use tab to navigate from the username field to the password field in the form, the password is correctly highlighted and cleared in FF, but not in IE8. In IE8, tabbing to the password field moves the cursor to the very beginning of the password box, leaving the default value (PASSWORD) in place, and not clearing it. Any idea on why this occurs? Is this a known bug or inherent flaw of IE8 that I will just have to hack around, or can I just add a wee bit of code somewhere to handle IE8 more correctly? If the problem isn't clear from my description I can attempt to elucidate or just throw up a screenshot/video clip, or upload a static copy of the HTML somewhere. (If the last one, I could use a recommendation of a good site or service to do this since the actual site is still in dev and not availabile to the web yet.) Thanks! Edit: Changing the onclick property to onfocus fixed that problem, but brought another one to light (see my comment #David). Could this be related to the way that checkKeyPress is written? It's a function I borrowed from elsewhere in the site. In particular I'm wondering if changing its return statements could be the fix. Maybe it shouldn't return true/false/anything at all? Edit 2: I removed the checkKeyPress method entirely to see if that was causing the problem, and it changed nothing. The full source is here. The div that focus randomly jumps to is the one between the two "global nav" comments, at the very top of the body. Still no idea why it's happening. To see if the focus was somehow just getting reset, I added another div above the one that focus is jumping to randomly, expecting focus to start jumping to the new div instead. It didn't. It still switches focus to the div with the image in it. I am utterly befuggled.
What if you put the check in onfocus instead of onclick? Tabbing to a field technically isn't a click anyways.
Since the lost focus seems to happen every 6000 milliseconds, I'd point the blame somewhere at expandone()/contractall() in /js/qm_scripts.js. Your login form is in the "dropmsg0" div, causing it to be briefly hidden and redisplayed every 6 seconds. The textboxes lose focus in IE8 when hidden. I'd either rename the div to exclude if from the ticker, or modify the ticker script to not run when there's only one dropmsg div.
POST unchecked HTML checkboxes
I've got a load of checkboxes that are checked by default. My users will probably uncheck a few (if any) of the checkboxes and leave the rest checked. Is there any way to make the form POST the checkboxes that are not checked, rather than the ones that are checked?
The solution I liked the most so far is to put a hidden input with the same name as the checkbox that might not be checked. I think it works so that if the checkbox isn't checked, the hidden input is still successful and sent to the server but if the checkbox is checked it will override the hidden input before it. This way you don't have to keep track of which values in the posted data were expected to come from checkboxes. <form> <input type='hidden' value='0' name='selfdestruct'> <input type='checkbox' value='1' name='selfdestruct'> </form>
Add a hidden input for the checkbox with a different ID: <input id='testName' type='checkbox' value='Yes' name='testName'> <input id='testNameHidden' type='hidden' value='No' name='testName'> Before submitting the form, disable the hidden input based on the checked condition: form.addEventListener('submit', () => { if(document.getElementById("testName").checked) { document.getElementById('testNameHidden').disabled = true; } }
I solved it by using vanilla JavaScript: <input type="hidden" name="checkboxName" value="0"><input type="checkbox" onclick="this.previousSibling.value=1-this.previousSibling.value"> Be careful not to have any spaces or linebreaks between this two input elements! You can use this.previousSibling.previousSibling to get "upper" elements. With PHP you can check the named hidden field for 0 (not set) or 1 (set).
My personal favorite is to add a hidden field with the same name that will be used if the check-box is unchecked. But the solution is not as easy as it may seems. If you add this code: <form> <input type='hidden' value='0' name='selfdestruct'> <input type='checkbox' value='1' name='selfdestruct'> </form> The browser will not really care about what you do here. The browser will send both parameters to the server, and the server has to decide what to do with them. PHP for example takes the last value as the one to use (see: Authoritative position of duplicate HTTP GET query keys) But other systems I worked with (based on Java) do it the way around - they offer you only the first value. .NET instead will give you an array with both elements instead I'll try to test this with node.js, Python and Perl at sometime.
you don't need to create a hidden field for all checkboxes just copy my code. it will change the value of checkbox if not checked the value will assign 0 and if checkbox checked then assign value into 1 $("form").submit(function () { var this_master = $(this); this_master.find('input[type="checkbox"]').each( function () { var checkbox_this = $(this); if( checkbox_this.is(":checked") == true ) { checkbox_this.attr('value','1'); } else { checkbox_this.prop('checked',true); //DONT' ITS JUST CHECK THE CHECKBOX TO SUBMIT FORM DATA checkbox_this.attr('value','0'); } }) })
A common technique around this is to carry a hidden variable along with each checkbox. <input type="checkbox" name="mycheckbox" /> <input type="hidden" name="mycheckbox.hidden"/> On the server side, we first detect list of hidden variables and for each of the hidden variable, we try to see if the corresponding checkbox entry is submitted in the form data or not. The server side algorithm would probably look like: for input in form data such that input.name endswith .hidden checkboxName = input.name.rstrip('.hidden') if chceckbName is not in form, user has unchecked this checkbox The above doesn't exactly answer the question, but provides an alternate means of achieving similar functionality.
I know this question is 3 years old but I found a solution that I think works pretty well. You can do a check if the $_POST variable is assigned and save it in a variable. $value = isset($_POST['checkboxname'] ? 'YES' : 'NO'; the isset() function checks if the $_POST variable is assigned. By logic if it is not assigned then the checkbox is not checked.
$('input[type=checkbox]').on("change",function(){ var target = $(this).parent().find('input[type=hidden]').val(); if(target == 0) { target = 1; } else { target = 0; } $(this).parent().find('input[type=hidden]').val(target); }); <p> <input type="checkbox" /> <input type="hidden" name="test_checkbox[]" value="0" /> </p> <p> <input type="checkbox" /> <input type="hidden" name="test_checkbox[]" value="0" /> </p> <p> <input type="checkbox" /> <input type="hidden" name="test_checkbox[]" value="0" /> </p> If you leave out the name of the checkbox it doesn't get passed. Only the test_checkbox array.
You can do some Javascript in the form's submit event. That's all you can do though, there's no way to get browsers to do this by themselves. It also means your form will break for users without Javascript. Better is to know on the server which checkboxes there are, so you can deduce that those absent from the posted form values ($_POST in PHP) are unchecked.
I also like the solution that you just post an extra input field, using JavaScript seems a little hacky to me. Depending on what you use for you backend will depend on which input goes first. For a server backend where the first occurrence is used (JSP) you should do the following. <input type="checkbox" value="1" name="checkbox_1"/> <input type="hidden" value="0" name="checkbox_1"/> For a server backend where the last occurrence is used (PHP,Rails) you should do the following. <input type="hidden" value="0" name="checkbox_1"/> <input type="checkbox" value="1" name="checkbox_1"/> For a server backend where all occurrences are stored in a list data type ([],array). (Python / Zope) You can post in which ever order you like, you just need to try to get the value from the input with the checkbox type attribute. So the first index of the list if the checkbox was before the hidden element and the last index if the checkbox was after the hidden element. For a server backend where all occurrences are concatenated with a comma (ASP.NET / IIS) You will need to (split/explode) the string by using a comma as a delimiter to create a list data type. ([]) Now you can attempt to grab the first index of the list if the checkbox was before the hidden element and grab the last index if the checkbox was after the hidden element. image source
I would actually do the following. Have my hidden input field with the same name with the checkbox input <input type="hidden" name="checkbox_name[]" value="0" /> <input type="checkbox" name="checkbox_name[]" value="1" /> and then when i post I first of all remove the duplicate values picked up in the $_POST array, atfer that display each of the unique values. $posted = array_unique($_POST['checkbox_name']); foreach($posted as $value){ print $value; } I got this from a post remove duplicate values from array
"I've gone with the server approach. Seems to work fine - thanks. – reach4thelasers Dec 1 '09 at 15:19" I would like to recommend it from the owner. As quoted: javascript solution depends on how the server handler (I didn't check it) such as if(!isset($_POST["checkbox"]) or empty($_POST["checkbox"])) $_POST["checkbox"]="something";
Most of the answers here require the use of JavaScript or duplicate input controls. Sometimes this needs to be handled entirely on the server-side. I believe the (intended) key to solving this common problem is the form's submission input control. To interpret and handle unchecked values for checkboxes successfully you need to have knowledge of the following: The names of the checkboxes The name of the form's submission input element By checking whether the form was submitted (a value is assigned to the submission input element), any unchecked checkbox values can be assumed. For example: <form name="form" method="post"> <input name="value1" type="checkbox" value="1">Checkbox One<br/> <input name="value2" type="checkbox" value="1" checked="checked">Checkbox Two<br/> <input name="value3" type="checkbox" value="1">Checkbox Three<br/> <input name="submit" type="submit" value="Submit"> </form> When using PHP, it's fairly trivial to detect which checkboxes were ticked. <?php $checkboxNames = array('value1', 'value2', 'value3'); // Persisted (previous) checkbox state may be loaded // from storage, such as the user's session or a database. $checkboxesThatAreChecked = array(); // Only process if the form was actually submitted. // This provides an opportunity to update the user's // session data, or to persist the new state of the data. if (!empty($_POST['submit'])) { foreach ($checkboxNames as $checkboxName) { if (!empty($_POST[$checkboxName])) { $checkboxesThatAreChecked[] = $checkboxName; } } // The new state of the checkboxes can be persisted // in session or database by inspecting the values // in $checkboxesThatAreChecked. print_r($checkboxesThatAreChecked); } ?> Initial data could be loaded on each page load, but should be only modified if the form was submitted. Since the names of the checkboxes are known beforehand, they can be traversed and inspected individually, so that the the absence of their individual values indicates that they are not checked.
I've tried Sam's version first. Good idea, but it causes there to be multiple elements in the form with the same name. If you use any javascript that finds elements based on name, it will now return an array of elements. I've worked out Shailesh's idea in PHP, it works for me. Here's my code: /* Delete '.hidden' fields if the original is present, use '.hidden' value if not. */ foreach ($_POST['frmmain'] as $field_name => $value) { // Only look at elements ending with '.hidden' if ( !substr($field_name, -strlen('.hidden')) ) { break; } // get the name without '.hidden' $real_name = substr($key, strlen($field_name) - strlen('.hidden')); // Create a 'fake' original field with the value in '.hidden' if an original does not exist if ( !array_key_exists( $real_name, $POST_copy ) ) { $_POST[$real_name] = $value; } // Delete the '.hidden' element unset($_POST[$field_name]); }
You can also intercept the form.submit event and reverse check before submit $('form').submit(function(event){ $('input[type=checkbox]').prop('checked', function(index, value){ return !value; }); });
I use this block of jQuery, which will add a hidden input at submit-time to every unchecked checkbox. It will guarantee you always get a value submitted for every checkbox, every time, without cluttering up your markup and risking forgetting to do it on a checkbox you add later. It's also agnostic to whatever backend stack (PHP, Ruby, etc.) you're using. // Add an event listener on #form's submit action... $("#form").submit( function() { // For each unchecked checkbox on the form... $(this).find($("input:checkbox:not(:checked)")).each( // Create a hidden field with the same name as the checkbox and a value of 0 // You could just as easily use "off", "false", or whatever you want to get // when the checkbox is empty. function(index) { var input = $('<input />'); input.attr('type', 'hidden'); input.attr('name', $(this).attr("name")); // Same name as the checkbox input.attr('value', "0"); // or 'off', 'false', 'no', whatever // append it to the form the checkbox is in just as it's being submitted var form = $(this)[0].form; $(form).append(input); } // end function inside each() ); // end each() argument list return true; // Don't abort the form submit } // end function inside submit() ); // end submit() argument list
$('form').submit(function () { $(this).find('input[type="checkbox"]').each( function () { var checkbox = $(this); if( checkbox.is(':checked')) { checkbox.attr('value','1'); } else { checkbox.after().append(checkbox.clone().attr({type:'hidden', value:0})); checkbox.prop('disabled', true); } }) });
I see this question is old and has so many answers, but I'll give my penny anyway. My vote is for the javascript solution on the form's 'submit' event, as some has pointed out. No doubling the inputs (especially if you have long names and attributes with php code mixed with html), no server side bother (that would require to know all field names and to check them down one by one), just fetch all the unchecked items, assign them a 0 value (or whatever you need to indicate a 'not checked' status) and then change their attribute 'checked' to true $('form').submit(function(e){ var b = $("input:checkbox:not(:checked)"); $(b).each(function () { $(this).val(0); //Set whatever value you need for 'not checked' $(this).attr("checked", true); }); return true; }); this way you will have a $_POST array like this: Array ( [field1] => 1 [field2] => 0 )
What I did was a bit different. First I changed the values of all the unchecked checkboxes. To "0", then selected them all, so the value would be submitted. function checkboxvalues(){ $("#checkbox-container input:checkbox").each(function({ if($(this).prop("checked")!=true){ $(this).val("0"); $(this).prop("checked", true); } }); }
I would prefer collate the $_POST if (!$_POST['checkboxname']) !$_POST['checkboxname'] = 0; it minds, if the POST doesn't have have the 'checkboxname'value, it was unckecked so, asign a value. you can create an array of your ckeckbox values and create a function that check if values exist, if doesn`t, it minds that are unchecked and you can asign a value
Might look silly, but it works for me. The main drawback is that visually is a radio button, not a checkbox, but it work without any javascript. HTML Initialy checked <span><!-- set the check attribute for the one that represents the initial value--> <input type="radio" name="a" value="1" checked> <input type="radio" name="a" value="0"> </span> <br/> Initialy unchecked <span><!-- set the check attribute for the one that represents the initial value--> <input type="radio" name="b" value="1"> <input type="radio" name="b" value="0" checked> </span> and CSS span input {position: absolute; opacity: 0.99} span input:checked {z-index: -10;} span input[value="0"] {opacity: 0;} fiddle here I'd like to hear any problems you find with this code, cause I use it in production
The easiest solution is a "dummy" checkbox plus hidden input if you are using jquery: <input id="id" type="hidden" name="name" value="1/0"> <input onchange="$('#id').val(this.checked?1:0)" type="checkbox" id="dummy-id" name="dummy-name" value="1/0" checked="checked/blank"> Set the value to the current 1/0 value to start with for BOTH inputs, and checked=checked if 1. The input field (active) will now always be posted as 1 or 0. Also the checkbox can be clicked more than once before submission and still work correctly.
Example on Ajax actions is(':checked') used jQuery instead of .val(); var params = { books: $('input#users').is(':checked'), news : $('input#news').is(':checked'), magazine : $('input#magazine').is(':checked') }; params will get value in TRUE OR FALSE..
Checkboxes usually represent binary data that are stored in database as Yes/No, Y/N or 1/0 values. HTML checkboxes do have bad nature to send value to server only if checkbox is checked! That means that server script on other site must know in advance what are all possible checkboxes on web page in order to be able to store positive (checked) or negative (unchecked) values. Actually only negative values are problem (when user unchecks previously (pre)checked value - how can server know this when nothing is sent if it does not know in advance that this name should be sent). If you have a server side script which dynamically creates UPDATE script there's a problem because you don't know what all checkboxes should be received in order to set Y value for checked and N value for unchecked (not received) ones. Since I store values 'Y' and 'N' in my database and represent them via checked and unchecked checkboxes on page, I added hidden field for each value (checkbox) with 'Y' and 'N' values then use checkboxes just for visual representation, and use simple JavaScript function check() to set value of if according to selection. <input type="hidden" id="N1" name="N1" value="Y" /> <input type="checkbox"<?php if($N1==='Y') echo ' checked="checked"'; ?> onclick="check(this);" /> <label for="N1">Checkbox #1</label> use one JavaScript onclick listener and call function check() for each checkboxe on my web page: function check(me) { if(me.checked) { me.previousSibling.previousSibling.value='Y'; } else { me.previousSibling.previousSibling.value='N'; } } This way 'Y' or 'N' values are always sent to server side script, it knows what are fields that should be updated and there's no need for conversion of checbox "on" value into 'Y' or not received checkbox into 'N'. NOTE: white space or new line is also a sibling so here I need .previousSibling.previousSibling.value. If there's no space between then only .previousSibling.value You don't need to explicitly add onclick listener like before, you can use jQuery library to dynamically add click listener with function to change value to all checkboxes in your page: $('input[type=checkbox]').click(function() { if(this.checked) { $(this).prev().val('Y'); } else { $(this).prev().val('N'); } });
#cpburnz got it right but to much code, here is the same idea using less code: JS: // jQuery OnLoad $(function(){ // Listen to input type checkbox on change event $("input[type=checkbox]").change(function(){ $(this).parent().find('input[type=hidden]').val((this.checked)?1:0); }); }); HTML (note the field name using an array name): <div> <input type="checkbox" checked="checked"> <input type="hidden" name="field_name[34]" value="1"/> </div> <div> <input type="checkbox"> <input type="hidden" name="field_name[35]" value="0"/> </div> <div> And for PHP: <div> <input type="checkbox"<?=($boolean)?' checked="checked"':''?>> <input type="hidden" name="field_name[<?=$item_id?>]" value="<?=($boolean)?1:0?>"/> </div>
All answers are great, but if you have multiple checkboxes in a form with the same name and you want to post the status of each checkbox. Then i have solved this problem by placing a hidden field with the checkbox (name related to what i want). <input type="hidden" class="checkbox_handler" name="is_admin[]" value="0" /> <input type="checkbox" name="is_admin_ck[]" value="1" /> then control the change status of checkbox by below jquery code: $(documen).on("change", "input[type='checkbox']", function() { var checkbox_val = ( this.checked ) ? 1 : 0; $(this).siblings('input.checkbox_handler').val(checkbox_val); }); now on change of any checkbox, it will change the value of related hidden field. And on server you can look only to hidden fields instead of checkboxes. Hope this will help someone have this type of problem. cheer :)
You can add hidden elements before submitting form. $('form').submit(function() { $(this).find('input[type=checkbox]').each(function (i, el) { if(!el.checked) { var hidden_el = $(el).clone(); hidden_el[0].checked = true; hidden_el[0].value = '0'; hidden_el[0].type = 'hidden' hidden_el.insertAfter($(el)); } }) });
The problem with checkboxes is that if they are not checked then they are not posted with your form. If you check a checkbox and post a form you will get the value of the checkbox in the $_POST variable which you can use to process a form, if it's unchecked no value will be added to the $_POST variable. In PHP you would normally get around this problem by doing an isset() check on your checkbox element. If the element you are expecting isn't set in the $_POST variable then we know that the checkbox is not checked and the value can be false. if(!isset($_POST['checkbox1'])) { $checkboxValue = false; } else { $checkboxValue = $_POST['checkbox1']; } But if you have created a dynamic form then you won't always know the name attribute of your checkboxes, if you don't know the name of the checkbox then you can't use the isset function to check if this has been sent with the $_POST variable.
function SubmitCheckBox(obj) { obj.value = obj.checked ? "on" : "off"; obj.checked = true; return obj.form.submit(); } <input type=checkbox name="foo" onChange="return SubmitCheckBox(this);">
If you want to submit an array of checkbox values (including un-checked items) then you could try something like this: <form> <input type="hidden" value="0" name="your_checkbox_array[]"><input type="checkbox">Dog <input type="hidden" value="0" name="your_checkbox_array[]"><input type="checkbox">Cat </form> $('form').submit(function(){ $('input[type="checkbox"]:checked').prev().val(1); });