Related
After reading through the comments on this post, I came up with the following syntax for the accept attribute:
Images
<input type="file" accept="image/jpeg, image/png, image/gif, .jpeg, .png, .gif">
Audio
<input type="file" accept="audio/mpeg, audio/x-wav, .mp3, .wav">
This works perfectly on desktop browsers, but does not appear to filter files at all on iOS or Android.
Are there any cross-browser solutions available?
I was unable to get the accept attribute to work for mobile. Ultimately I had to add an onchange handler to the input (general idea shown below).
Keep in mind, you'll still want to use the accept attribute as shown in my question, because it will work on desktop.
const supportedExtensions = ['jpeg', 'jpg', 'png', 'gif'];
const handleChange = ({ target }) => {
const path = target.value.split('.');
const extension = `${path[path.length - 1]}`;
if (supportedExtensions.includes(extension)) {
// TODO: upload
} else {
// TODO: show "invalid file type" message to user
// reset value
target.value = '';
}
}
The detail listing of browser support for "accept" attribute is listed in w3 schools. Have a look. It may help you.
I got the same problem, found this page, here is my workaround using onChange event.
I know this isn't true filtering and this is pretty ugly (I don't it), but it works indeed. I tested on my iOS and Android devices.
<script type="text/javascript">
let file;
function checkFile() {
file = document.querySelector('input[type=file]').files[0];
if (file.type != "image/png") {
file = null;
document.getElementById('image').remove();
let div = document.getElementById('div');
let image = document.createElement('input');
image.setAttribute('type', 'file');
image.setAttribute('id', 'image');
image.setAttribute('accept', 'image/png');
image.setAttribute('onchange', 'checkFile()');
div.appendChild(image);
window.alert('unsupported file type');
}
}
</script>
<div id="div">
<input type="file" id="image" accept="image/png" onchange="checkFile()">
</div>
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.
first, if anyone has another more specific and better title for this question please tell me and I'll change. I've never been good at using Google so...
I'm currently using following code to create an input field
<input name="igname" type="text" maxlength="40" autofocus="autofocus" value="Hi">
It works fine, but there's just one problem -> the cursor is on the left, I want it to be on the right but I don't have any idea how to do so.
Thanks in advance
JoDev's answer does not seem to work with FF and could be simplified. el is the DOM element representing the input.
function moveCursorToEnd(el) {
'use strict';
var index=el.value.length;
el.focus();
el.setSelectionRange(index,index);
}
First idea
Use style='text-align:right' to change the text align.
PUT THE CURSOR TO THE END
To put the cursor to the end of editable element, use this : tested function | fiddle
For the fiddle, it works great on Chrome, but in FF, you have to give focus to the element because the IFRAME haven't got focus by default!
moveCursorToEnd = function(el, focused) {
console.log('go');
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
if(!focused)
el.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
if(!focused)
el.focus();
}
onbodyload = function() {
elem = document.getElementById('totheend');
moveCursorToEnd(elem);
}
<body onload='onbodyload()'>...
<input class='totheend' onfocus="if(typeof moveCursorToEnd != 'undefined') moveCursorToEnd(this, true)" name="igname" type="text" maxlength="40" autofocus="autofocus" value="Hi" >
I have a form with several different fieldsets. I have some jQuery that displays the field sets to the users one at a time. For browsers that support HTML5 validation, I'd love to make use of it. However, I need to do it on my terms. I'm using JQuery.
When a user clicks a JS Link to move to the next fieldset, I need the validation to happen on the current fieldset and block the user from moving forward if there is issues.
Ideally, as the user loses focus on an element, validation will occur.
Currently have novalidate going and using jQuery. Would prefer to use the native method. :)
TL;DR: Not caring about old browsers? Use form.reportValidity().
Need legacy browser support? Read on.
It actually is possible to trigger validation manually.
I'll use plain JavaScript in my answer to improve reusability, no jQuery is needed.
Assume the following HTML form:
<form>
<input required>
<button type="button">Trigger validation</button>
</form>
And let's grab our UI elements in JavaScript:
var form = document.querySelector('form')
var triggerButton = document.querySelector('button')
Don't need support for legacy browsers like Internet Explorer? This is for you.
All modern browsers support the reportValidity() method on form elements.
triggerButton.onclick = function () {
form.reportValidity()
}
That's it, we're done. Also, here's a simple CodePen using this approach.
Approach for older browsers
Below is a detailed explanation how reportValidity() can be emulated in older browsers.
However, you don't need to copy&paste those code blocks into your project yourself — there is a ponyfill/polyfill readily available for you.
Where reportValidity() is not supported, we need to trick the browser a little bit. So, what will we do?
Check validity of the form by calling form.checkValidity(). This will tell us if the form is valid, but not show the validation UI.
If the form is invalid, we create a temporary submit button and trigger a click on it. Since the form is not valid, we know it won't actually submit, however, it will show validation hints to the user. We'll remove the temporary submit button immedtiately, so it will never be visible to the user.
If the form is valid, we don't need to interfere at all and let the user proceed.
In code:
triggerButton.onclick = function () {
// Form is invalid!
if (!form.checkValidity()) {
// Create the temporary button, click and remove it
var tmpSubmit = document.createElement('button')
form.appendChild(tmpSubmit)
tmpSubmit.click()
form.removeChild(tmpSubmit)
} else {
// Form is valid, let the user proceed or do whatever we need to
}
}
This code will work in pretty much any common browser (I've tested it successfully down to IE11).
Here's a working CodePen example.
You can't trigger the native validation UI (see edit below), but you can easily take advantage of the validation API on arbitrary input elements:
$('input').blur(function(event) {
event.target.checkValidity();
}).bind('invalid', function(event) {
setTimeout(function() { $(event.target).focus();}, 50);
});
The first event fires checkValidity on every input element as soon as it loses focus, if the element is invalid then the corresponding event will be fired and trapped by the second event handler. This one sets the focus back to the element, but that could be quite annoying, I assume you have a better solution for notifying about the errors. Here's a working example of my code above.
EDIT: All modern browsers support the reportValidity() method for native HTML5 validation, per this answer.
In some extent, You CAN trigger HTML5 form validation and show hints to user without submitting the form!
Two button, one for validate, one for submit
Set a onclick listener on the validate button to set a global flag(say justValidate) to indicate this click is intended to check the validation of the form.
And set a onclick listener on the submit button to set the justValidate flag to false.
Then in the onsubmit handler of the form, you check the flag justValidate to decide the returning value and invoke the preventDefault() to stop the form to submit. As you know, the HTML5 form validation(and the GUI hint to user) is preformed before the onsubmit event, and even if the form is VALID you can stop the form submit by returning false or invoke preventDefault().
And, in HTML5 you have a method to check the form's validation: the form.checkValidity(), then in you can know if the form is validate or not in your code.
OK, here is the demo:
http://jsbin.com/buvuku/2/edit
var field = $("#field")
field.keyup(function(ev){
if(field[0].value.length < 10) {
field[0].setCustomValidity("characters less than 10")
}else if (field[0].value.length === 10) {
field[0].setCustomValidity("characters equal to 10")
}else if (field[0].value.length > 10 && field[0].value.length < 20) {
field[0].setCustomValidity("characters greater than 10 and less than 20")
}else if(field[0].validity.typeMismatch) {
field[0].setCustomValidity("wrong email message")
}else {
field[0].setCustomValidity("") // no more errors
}
field[0].reportValidity()
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="email" id="field">
Somewhat easy to make add or remove HTML5 validation to fieldsets.
$('form').each(function(){
// CLEAR OUT ALL THE HTML5 REQUIRED ATTRS
$(this).find('.required').attr('required', false);
// ADD THEM BACK TO THE CURRENT FIELDSET
// I'M JUST USING A CLASS TO IDENTIFY REQUIRED FIELDS
$(this).find('fieldset.current .required').attr('required', true);
$(this).submit(function(){
var current = $(this).find('fieldset.current')
var next = $(current).next()
// MOVE THE CURRENT MARKER
$(current).removeClass('current');
$(next).addClass('current');
// ADD THE REQUIRED TAGS TO THE NEXT PART
// NO NEED TO REMOVE THE OLD ONES
// SINCE THEY SHOULD BE FILLED OUT CORRECTLY
$(next).find('.required').attr('required', true);
});
});
I seem to find the trick:
Just remove the form target attribute, then use a submit button to validate the form and show hints, check if form valid via JavaScript, and then post whatever. The following code works for me:
<form>
<input name="foo" required>
<button id="submit">Submit</button>
</form>
<script>
$('#submit').click( function(e){
var isValid = true;
$('form input').map(function() {
isValid &= this.validity['valid'] ;
}) ;
if (isValid) {
console.log('valid!');
// post something..
} else
console.log('not valid!');
});
</script>
Html Code:
<form class="validateDontSubmit">
....
<button style="dislay:none">submit</button>
</form>
<button class="outside"></button>
javascript( using Jquery):
<script type="text/javascript">
$(document).on('submit','.validateDontSubmit',function (e) {
//prevent the form from doing a submit
e.preventDefault();
return false;
})
$(document).ready(function(){
// using button outside trigger click
$('.outside').click(function() {
$('.validateDontSubmit button').trigger('click');
});
});
</script>
Hope this will help you
For input field
<input id="PrimaryPhNumber" type="text" name="mobile" required
pattern="^[789]\d{9}$" minlenght="10" maxLength="10" placeholder="Eg: 9444400000"
class="inputBoxCss"/>
$('#PrimaryPhNumber').keyup(function (e) {
console.log(e)
let field=$(this)
if(Number(field.val()).toString()=="NaN"){
field.val('');
field.focus();
field[0].setCustomValidity('Please enter a valid phone number');
field[0].reportValidity()
$(":focus").css("border", "2px solid red");
}
})
$('#id').get(0).reportValidity();
This will trigger the input with ID specified. Use ".classname" for classes.
When there is a very complex (especially asynchronous) validation process, there is a simple workaround:
<form id="form1">
<input type="button" onclick="javascript:submitIfVeryComplexValidationIsOk()" />
<input type="submit" id="form1_submit_hidden" style="display:none" />
</form>
...
<script>
function submitIfVeryComplexValidationIsOk() {
var form1 = document.forms['form1']
if (!form1.checkValidity()) {
$("#form1_submit_hidden").click()
return
}
if (checkForVeryComplexValidation() === 'Ok') {
form1.submit()
} else {
alert('form is invalid')
}
}
</script>
Another way to resolve this problem:
$('input').oninvalid(function (event, errorMessage) {
event.target.focus();
});
There is no way to have a tri-state check button (yes, no, null) in HTML, right?
Are there any simple tricks or work-arounds without having to render the whole thing by oneself?
Edit — Thanks to Janus Troelsen's comment, I found a better solution:
HTML5 defines a property for checkboxes called indeterminate
See w3c reference guide. To make checkbox appear visually indeterminate set it to true:
element.indeterminate = true;
Here is Janus Troelsen's fiddle. Note, however, that:
The indeterminate state cannot be set in the HTML markup, it can only be done via Javascript (see this JSfiddle test and this detailed article in CSS tricks)
This state doesn't change the value of the checkbox, it is only a visual cue that masks the input's real state.
Browser test: Worked for me in Chrome 22, Firefox 15, Opera 12 and back to IE7. Regarding mobile browsers, Android 2.0 browser and Safari mobile on iOS 3.1 don't have support for it.
Previous answer
Another alternative would be to play with the checkbox transparency
for the "some selected" state (as Gmail does used to
do in previous versions). It will require some javascript and a CSS
class. Here I put a particular example that handles a list with
checkable items and a checkbox that allows to select all/none of them.
This checkbox shows a "some selected" state when some of the list
items are selected.
Given a checkbox with an ID #select_all and several checkboxes with
a class .select_one,
The CSS class that fades the "select all" checkbox would be the
following:
.some_selected {
opacity: 0.5;
filter: alpha(opacity=50);
}
And the JS code that handles the tri-state of the select all checkbox
is the following:
$('#select_all').change (function ()
{
//Check/uncheck all the list's checkboxes
$('.select_one').attr('checked', $(this).is(':checked'));
//Remove the faded state
$(this).removeClass('some_selected');
});
$('.select_one').change (function ()
{
if ($('.select_one:checked').length == 0)
$('#select_all').removeClass('some_selected').attr('checked', false);
else if ($('.select_one:not(:checked)').length == 0)
$('#select_all').removeClass('some_selected').attr('checked', true);
else
$('#select_all').addClass('some_selected').attr('checked', true);
});
You can try it here: http://jsfiddle.net/98BMK/
You could use HTML's indeterminate IDL attribute on input elements.
My proposal would be using
three appropriate unicode characters for the three states e.g. ❓,✅,❌
a plain text input field (size=1)
no border
read only
display no cursor
onclick handler to toggle thru the three states
See examples at:
http://jsfiddle.net/wf_bitplan_com/941std72/8/
/**
* loops thru the given 3 values for the given control
*/
function tristate(control, value1, value2, value3) {
switch (control.value.charAt(0)) {
case value1:
control.value = value2;
break;
case value2:
control.value = value3;
break;
case value3:
control.value = value1;
break;
default:
// display the current value if it's unexpected
alert(control.value);
}
}
function tristate_Marks(control) {
tristate(control,'\u2753', '\u2705', '\u274C');
}
function tristate_Circles(control) {
tristate(control,'\u25EF', '\u25CE', '\u25C9');
}
function tristate_Ballot(control) {
tristate(control,'\u2610', '\u2611', '\u2612');
}
function tristate_Check(control) {
tristate(control,'\u25A1', '\u2754', '\u2714');
}
<input type='text'
style='border: none;'
onfocus='this.blur()'
readonly='true'
size='1'
value='❓' onclick='tristate_Marks(this)' />
<input style="border: none;"
id="tristate"
type="text"
readonly="true"
size="1"
value="❓"
onclick="switch(this.form.tristate.value.charAt(0)) {
case '❓': this.form.tristate.value='✅'; break;
case '✅': this.form.tristate.value='❌'; break;
case '❌': this.form.tristate.value='❓'; break;
};" />
You can use radio groups to achieve that functionality:
<input type="radio" name="choice" value="yes" />Yes
<input type="radio" name="choice" value="No" />No
<input type="radio" name="choice" value="null" />null
Here is a runnable example using the mentioned indeterminate attribute:
const indeterminates = document.getElementsByClassName('indeterminate');
indeterminates['0'].indeterminate = true;
<form>
<div>
<input type="checkbox" checked="checked" />True
</div>
<div>
<input type="checkbox" />False
</div>
<div>
<input type="checkbox" class="indeterminate" />Indeterminate
</div>
</form>
Just run the code snippet to see how it looks like.
You can use an indeterminate state: http://css-tricks.com/indeterminate-checkboxes/. It's supported by the browsers out of the box and don't require any external js libraries.
I think that the most semantic way is using readonly attribute that checkbox inputs can have. No css, no images, etc; a built-in HTML property!
See Fiddle:
http://jsfiddle.net/chriscoyier/mGg85/2/
As described here in last trick:
http://css-tricks.com/indeterminate-checkboxes/
Like #Franz answer you can also do it with a select. For example:
<select>
<option></option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
With this you can also give a concrete value that will be send with the form, I think that with javascript indeterminate version of checkbox, it will send the underline value of the checkbox.
At least, you can use it as a callback when javascript is disabled. For example, give it an id and in the load event change it to the javascript version of the checkbox with indeterminate status.
Besides all cited above, there are jQuery plugins that may help too:
for individual checkboxes:
jQuery-Tristate-Checkbox-plugin: http://vanderlee.github.io/tristate/
for tree-like behavior checkboxes:
jQuery Tristate: http://jlbruno.github.io/jQuery-Tristate-Checkbox-plugin/
EDIT
Both libraries uses the 'indeterminate' checkbox attribute, since this attribute in Html5 is just for styling (https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state), the null value is never sent to the server (checkboxes can only have two values).
To be able to submit this value to the server, I've create hidden counterpart fields which are populated on form submission using some javascript. On the server side, you'd need to check those counterpart fields instead of original checkboxes, of course.
I've used the first library (standalone checkboxes) where it's important to:
Initialize the checked, unchecked, indeterminate values
use .val() function to get the actual value
Cannot make work .state (probably my mistake)
Hope that helps.
Refering to #BoltClock answer, here is my solution for a more complex recursive method:
http://jsfiddle.net/gx7so2tq/2/
It might not be the most pretty solution but it works fine for me and is quite flexible.
I use two data objects defining the container:
data-select-all="chapter1"
and the elements itself:
data-select-some="chapter1"
Both having the same value. The combination of both data-objects within one checkbox allows sublevels, which are scanned recursively. Therefore two "helper" functions are needed to prevent the change-trigger.
Here other Example with simple jQuery and property data-checked:
$("#checkbox")
.click(function(e) {
var el = $(this);
switch (el.data('checked')) {
// unchecked, going indeterminate
case 0:
el.data('checked', 1);
el.prop('indeterminate', true);
break;
// indeterminate, going checked
case 1:
el.data('checked', 2);
el.prop('indeterminate', false);
el.prop('checked', true);
break;
// checked, going unchecked
default:
el.data('checked', 0);
el.prop('indeterminate', false);
el.prop('checked', false);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label><input type="checkbox" name="checkbox" value="" checked id="checkbox"> Tri-State Checkbox </label>
As I needed something like this -without any plug-in- for script-generated checkboxes in a table... I ended up with this solution:
<!DOCTYPE html>
<html>
<body>
Toto <input type="checkbox" id="myCheck1" onclick="updateChkBx(this)" /><br />
Tutu <input type="checkbox" id="myCheck2" onclick="updateChkBx(this)" /><br />
Tata <input type="checkbox" id="myCheck3" onclick="updateChkBx(this)" /><br />
Tete <input type="checkbox" id="myCheck4" onclick="updateChkBx(this)" /><br />
<script>
var chkBoxState = [];
function updateChkBx(src) {
var idx = Number(src.id.substring(7)); // 7 to bypass the "myCheck" part in each checkbox id
if(typeof chkBoxState[idx] == "undefined") chkBoxState[idx] = false; // make sure we can use stored state at first call
// the problem comes from a click on a checkbox both toggles checked attribute and turns inderminate attribute to false
if(chkBoxState[idx]) {
src.indeterminate = false;
src.checked = false;
chkBoxState[idx] = false;
}
else if (!src.checked) { // passing from checked to unchecked
src.indeterminate = true;
src.checked = true; // force considering we are in a checked state
chkBoxState[idx] = true;
}
}
// to know box state, just test indeterminate, and if not indeterminate, test checked
</script>
</body>
</html>
A short snippet using an auxiliary variable and indeterminate:
cb1.state = 1
function toggle_tristate(cb) {
cb.state = ++cb.state % 3 // cycle through 0,1,2
if (cb.state == 0) {
cb.indeterminate = true;
cb.checked = true; // after 'indeterminate' the state 'false' follows
}
}
<input id="cb1" type="checkbox" onclick="toggle_tristate(this)">
Only state==0 is captured. The rest is handle automatically.
http://jsfiddle.net/6vyek2c5
You'll need to use javascript/css to fake it.
Try here for an example: http://www.dynamicdrive.com/forums/archive/index.php/t-26322.html
It's possible to have HTML form elements disabled -- wouldn't that do? Your users would see it in one of three states, i.e. checked, unchecked, and disabled, which would be greyed out and not clickable. To me, that seems similar to "null" or "not applicable" or whatever you're looking for in that third state.
There's a simple JavaScript tri-state input field implementation at
https://github.com/supernifty/tristate-checkbox
The jQuery plugin "jstree" with the checkbox plugin can do this.
http://www.jstree.com/documentation/checkbox
-Matt
Building on the answers above using the indeterminate state, I've come up with a little bit that handles individual checkboxes and makes them tri-state.
MVC razor uses 2 inputs per checkbox anyway (the checkbox and a hidden with the same name to always force a value in the submit). MVC uses things like "true" as the checkbox value and "false" as the hidden of the same name; makes it amenable to boolean use in API calls. This snippet uses a third hidden state to persist the last request values across submits.
Checkboxes initialized with the below will start indeterminate. Checking once turns on the checkbox. Checking twice turns off the checkbox (returning the hidden value of the same name). Checking a third time returns it to indeterminate (and clears out the hidden so a submit will produce a blank).
The page also populates another hidden (e.g., triBox2Orig) with whatever value was on the query string to start, so the 3 states can be initialized and persisted between submits.
$(document).ready(function () {
var initCheckbox = function (chkBox)
{
var hidden = $('[name="' + $(chkBox).prop("name") + '"][type="hidden"]');
var hiddenOrig = $('[name="' + $(chkBox).prop("name") + 'Orig"][type="hidden"]').prop("value");
hidden.prop("origValue", hidden.prop("value"));
if (!chkBox.prop("checked") && !hiddenOrig) chkBox.prop("indeterminate", true);
if (chkBox.prop("indeterminate")) hidden.prop("value", null);
chkBox.change(checkBoxToggleFun);
}
var checkBoxToggleFun = function ()
{
var isChecked = $(this).prop('checked');
var hidden = $('[name="' + $(this).prop("name") + '"][type="hidden"]');
var thirdState = isChecked && hidden.prop("value") === hidden.prop("origValue");
if (thirdState) { // on 3rd click of a checkbox, set it back to indeterminate
$(this).prop("indeterminate", true);
$(this).prop('checked', false);
}
hidden.prop("value", thirdState ? null : hidden.prop("origValue"));
};
var chkBox = $('#triBox1');
initCheckbox(chkBox);
chkBox = $('#triBox2');
initCheckbox(chkBox);
});