javascript - hide mobile default keyboard but keep input field active - javascript

In HTML/CSS/JS I would like to be able to hide the default keyboard on mobile from the screen when an input field gets focus.
The situation is this: I have a web solution on a handheld device (Android 5+, running something based on Chromium) with a built-in 2D scanner - for reading barcodes.
Some fields should by default get input from scanning barcodes and I would very much like to hide the default keyboard that otherwise appear on screen. Then, if necessary, I would like to have some option of actually displaying the default keyboard anyway, for example by some button or selection on the page.
I have read the various suggestions to similar questions (mostly making the field readonly, but also the one about blurring the field right after it gets focus) but these do not work, as the scanner does not input anything into the field - it needs the field to have focus.

Thank you for the replies. As the consensus is that this is not possible I did a work-around that I am posting here:
The basic principle is to blur the input field and then capture the keypresses to add them to the input field anyway.
In this situation I am using a barcode scanner with all-numeric barcodes so that's what this will work with but if someone else should be interested it should be trivial to adapt to other situations:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script>
$( document ).ready( function () {
// _input_fields and _scan_fields are jQuery objects with the relevant elements
let _input_fields = $("input[type=number], input[type=text], input:not([type]), select");
let _scan_fields = $("input[type=number].scanner");
// _ignore is set to true when a scannable field actually _should_ get focus
var _ignore = false;
// onfocus() for relevant input fields on page
_input_fields.focus(function(){
// only do something if scannable fields shouldn't actually get focus
if (!_ignore) {
// outer is the current input field that is getting focus
let outer = this;
// found is set to true if the current input field is scannable
let found = false;
// loop through all scannable fields to see if the current input field is one of them
_scan_fields.each(function(index) {
// inner is one of the scannable fields, possibly the current input field
let inner = this;
// _field stores the current input field _if_ it is scannable
var _field;
// only check (and potentially reset key capture) if we have not found the current
// input field to be one of the scannable fields (yet)
if (!found) {
// check if the current input field "outer" is the currently examined
// scannable field "inner"
if (inner == outer) {
// the current input field is one of the scannable fields
// immediately remove focus to disable mobile keyboard
inner.blur();
// remember which input field we have found and disable further checks
_field = inner;
found = true;
// remove any existing keycapture (might destroy existing functionality!!!)
$(document).off("keypress");
// capture keypresses and add numbers to the input field
$(document).keypress(function(event){
var _field = inner;
let keynum = event.which;
if (keynum == 13) { // enter
// ignore or submit?
} else if ((keynum < 48) || (keynum > 57)) {
// not-a-number, ignore in this case
} else {
// a number, add to field value
$(_field).val($(_field).val() + String.fromCharCode(event.which));
}
});
} else {
// this is a regular field
// remove any existing keycapture (might destroy existing functionality!!!)
$(document).off("keypress");
}
}
});
}
});
// add a button after each scannable input field
$("input[type=number].scanner").after(function(){
return "<button class='descanner'>123</button>";
});
// if those buttons are pressed, the input field before them actually gets focus
// overriding the new behaviour
$("button.descanner").click(function(event){
// these buttons do not submit the form
event.preventDefault();
// remove any existing keycapture (might destroy existing functionality!!!)
$(document).off("keypress");
// set focus for the input field but make sure we don't catch this above
// also, clear content of input field
_ignore = true;
$(this).prev("input[type=number].scanner").val("").focus();
_ignore = false;
});
});
</script>
</head>
<body>
<form>
<input type="number" name="field1" class="" />
<input type="text" name="field2" class="" />
<input name="field3" class="" />
<select name="field4" class="">
<option value="bac">abc</option>
</select>
<input type="number" name="field5" class="scanner" />
<input type="number" name="field6" class="" />
<input type="number" name="field7" class="scanner" />
</form>
</body>
</html>
The form has 7 fields and 2 of those have the desired functionality. To enable manual edit of those fields a button is added next to each of those 2 fields.
This has been tested in Chrome 55 and on a Zebra TC 51 with Webview updated to Chromium 55.

Define an Input element above and append CSS property which will
hide the soft keyboard to popping up.
Set Focus to make ready for
scanner input in the text field.
The last Step Turn Read-only mode off to input data.
yourInputVal = document.getElementById('myInputElement');
yourInputVal.readOnly = true;
yourInputVal.focus();
setTimeout(function(){
document.getElementById('myInputElement').readOnly = false;
},

This worked for me:
Add the inputmode="none" attribute to your input element.
<input type="text" id="manageBinsBinId" inputmode="none" >
Javascript/jquery:
$(function() {
$(document).on(`focus`,`input`,function() {
myEl=$(this);
setTimeout(function(){
myEl.attr(`inputmode`,``);
},1);
});
$(document).on(`blur`,`input`, function(){
$(this).attr(`inputmode`,`none`);
});
});

Related

How can I force a user to fill in input fields successively?

I am looking to create an input form that will force a user to enter something in each field successively before moving onto the next input or submitting. This is something that would be filled out by someone on a phone who is asking questions that are attached to each input field and recording the answer in the inputs. Thus to prevent someone from skipping/missing a question while on the phone, I want to require that each input field is filled out successively. For this reason, the HTML 'required' attribute does not necessarily work as it will only prevent submission if a field is not filled out.
Previously I have given each required input its own submit button, but this looks horrible and can be confusing for those who use it. What is the best way to achieve what I am looking do to using a combination of html, js, node, and/or ejs?
Give each input a change event handler that makes the next input visible:
// Get all the labels into a node list
const labels = document.querySelectorAll("label");
// Get a reference to the last label
const lastLabel = labels[labels.length-1];
// Get a reference to a verification element
const output = document.querySelector("div.hidden");
// Use event delegation to handle all change events
document.addEventListener("change", function(event){
// Get reference to the parent label of the changed element
const lbl = event.target.closest("label");
// Check to see if it's an element we care to handle
if(lbl.classList.contains("response")){
// Hide the changed label (and it's child input)
lbl.classList.add("hidden");
// Unhide the next label (and it's input child)
lbl.nextElementSibling.classList.remove("hidden");
}
// If the current label was the last one
if(lbl === lastLabel){
// Show the verification field
output.classList.remove("hidden")
}
});
.hidden { display:none; }
<label class="response">#1<input ></label>
<label class="response hidden">#2<input ></label>
<label class="response hidden">#3<input ></label>
<div class="hidden">DONE!</div>

How to display "Please fill out this field" for all empty and required fields in html form?

I have a form as shown in the fiddle https://jsfiddle.net/vrn7zx5h/3/ in which I want to show the warning sign "Please fill out this field" at the same time for all unfilled required fields.
I found the answer on SO (as shown below) but i am not sure how to integrate with the fiddle.
function checkName(val){
if(/^[^-\s][\w\s]+$/.test(val)){
return true;
}else{
if(val.length != 0){
return false;
}
}
}
Problem Statement:
I am wondering what changes I should make in the fiddle so that the above pasted SO answer works with the fiddle.
Here is a JS fiddle that will show all error at one time. It is just barebone and not fancy. You'll need to make it fancy on your own. I also disabled the built-in validator as well with novalidate in the form tag.
https://jsfiddle.net/6kxc9hmq/1/
FYI: I also did not put in the functionality to hide the error message on next run, if the input now satisfies the condition.
Basically, I attached a submit event handler to the form and if the validator returned false, I told the form to not submit. Works only on IE9+ (I think) all the other browsers are usually fine with this method. The validator is basically just checking if the value of the input met the condition that I specified.
document.getElementById('form').addEventListener('submit', function(e) {
if(!validate())
e.preventDefault();
});
I think it should look like this, if I understand what you mean
<form action="">
Username: <input type="text" name="usrname">
Password: <input type="password" name="Password">
<input type="submit">
</form>
<p><strong>Note:</strong> The required attribute of the input tag is not
supported in Internet Explorer 9 and earlier versions.</p>
<script>
// append the listeners
document.forms[0].addEventListener('submit', function(evt){
if([
checkName(this.querySelector('[name="usrname"')),
checkName(this.querySelector('[name="Password"'))
].some((v)=>v)) {
evt.preventDefault()
}
})
// check is empty, then notify
function checkName(element){
// if you just have to check if is empty, this is enough
if(element.value) {
return
}
notify(element)
return true
}
// print the message
function notify(element) {
if(element.nextElementSibling.classList.contains('notify')) {
return;
}
element.parentNode.insertBefore(
Object.assign(document.createElement('p'),
{
className: 'notify',
innerHTML: 'Please fill out this field for all empty and required fields'
}
), element.nextSibling)
}
</script>
In your form, add empty divs after each input element. And you can conditionally display messages in the div in your validation. E.g if(name ==‘ ‘){div.innerHTML = ‘please enter your name’}
The required Attribute
Add the required attribute to your form.
The required attribute tells the browser to only submit the form if the field in question is filled out. Obviously, this means that the field can’t be left empty, but it also means that, depending on other attributes or the field’s type, only certain types of values will be accepted.

How to make textbox mandatory for certain radio buttons using jQuery?

I am working with JSP and I have a HTML form in which I have a button at the top which is Process button. Now if I click on that Process button, it shows me a form which has two radio button - TestClient and TestServer.
It also has Submit button in that form.
Here is my JSFiddle.
Now what I am trying to do is - As soon as I click on TestClient radio button, I need to type in firstName textbox and lastName textbox before pressing Submit button. Meaning these two textbox are mandatory for TestClient radio button and if somebody has typed in third textbox for TestClient radio button, then it should show error message next to that textbox. But If I am clicking TestServer radio button, all the three textbox are mandatory, meaning I need to type in something in all the three textbox.
May be, I can use disable Submit button feature as well if certain conditions are not met along with the proper message next to the textbox?
I am new to jQuery so still learning.
I think the best thing to do here to avoid confusing your users would be to hide() the unnecessary field like this. When the TestClient button is selected, the address field is hidden, but when the TestServer button is selected, it is shown. This avoids confusion with which boxes to fill in: people tend to dislike error messages, even if they are phrased kindly.
try out this fiddle
for figuring out if the form is submittable, you can use a submittable method to detect whether required inputs have a value:
// update submit button
function submittable() {
// get all required fields (needs to happen each time)
var $required = $('input[required=required]', '#form_process'),
$submittable = true;
$required.each(function() {
if ($(this).val()) {
// nothing
} else {
$submittable = false;
}
});
return $submittable;
}
in order for this to work properly, you need to make sure that your universally required inputs have a required attribute and your optionally required address input does not
<input name="fname" id="fname" placeholder="firstName" required="required">
<input name="lname" id="lname" placeholder="lastName" required="required">
<input name="address" id="address" placeholder="address">
then the validate method which will use the submittable method to validate the form and disable/enable the button
var $submit = $('#submit');
// validate control
function validate() {
if (submittable()) {
// you are valid
//alert('valid');
$submit.attr('disabled',false);
} else {
// you are not valid
//alert('invalid');
$submit.attr('disabled',true);
}
}
then you initially run the validate method
// run initial validation
validate();
and then run it on keyup of all the form inputs
// run validation on input keyup
$('#form_process input').keyup(function() {
validate();
});
you also need a method to get the currently checked radio that will show/hide the extra input. you also need to make that address input required when you need it so that you can include it in the validate method:
var $address = $('#address'),
$server = $('#server');
function getChecked() {
// find currently checked input
var $checked = $('input[name=client]:checked', '#form_process');
// if it is server
if ($checked.attr('id') === 'server') {
//alert('server!');
$address.show();
$address.attr('required',true);
} else {
//alert('client!');
$address.hide();
$address.attr('required',false);
}
}
in order for this to work properly, you should set one of your radios to checked
<input type="radio" name="client" id="client" value="TestClient" checked="checked">TestClient
<input type="radio" name="client" id="server" value="TestServer">TestServer
then you call the getChecked method initially and then whenever a radio value changes (along with the validate method):
// call initial get checked
getChecked();
// for each radio
$('input[type=radio]').each(function() {
// when it changes
$(this).change(function() {
// get checked radio
getChecked();
// run validation
validate();
});
});
edit
I should note that this solution is very specific to this issue. if you were to have more than 2 radios with varying input combinations, the getChecked() function would probably need to be a bit more sophisticated.
additionally, $('input[type=radio]').each() would need to be more specific if you have multiple radio groups. in which case you should probably add a class to each radio $('input.specific-radios').each() or wrap them in a parent $('.specific-radios-group input[type=radio]').each()

Force iOS numeric keyboard with custom / currency pattern

Is there a possiblity to force an iOS-device to show the numeric keyboard while using a custom pattern as input type?
my input pattern:
<input id="price" class="numeric" pattern="\d+((\.|,)\d{1,2})?" name="price"
title="" data-mini="true" data-clear-btn="true" autocomplete="off" autofocus />
I want to type a currency value like '14.99' and show up a keyboard with access to numbers on the iOS device
<input type='number' />
<input pattern='[0-9]*' />
<input pattern='[\d]*' />
are all missing the decimal sign and/or are not validating as number when adding a decimal sign. An alternative way could be a javascript function which is creating the decimal sign on the right place, like pressing 1->2->9->9 in this order creates on keypress() 0.01->0.12->1.29->12.99,
but this requires the input field to be type='text' --> obvious problem here is that the text keyboard is showed when focussing the input field.
How can I solve this issue?
EDIT
Environment:
JQM 1.3.2
jquery 1.8.2
For now, JavaScript is the only solution. Here's the simplest way to do it (using jQuery):
HTML
<input type="text">
JavaScript
$('input[type="text"]').on('touchstart', function() {
$(this).attr('type', 'number');
});
$('input[type="text"]').on('keydown blur', function() {
$(this).attr('type', 'text');
});
The idea is simple. The input starts off and ends up with type="text", but it briefly becomes type="number" on the touchstart event. This causes the correct iOS keyboard to appear. As soon as the user begins to enter any input or leave the field, the input becomes type="text" once again, thus circumventing the validation.
There's one downside to this method. When the user returns to an input that has already been filled out, the input will be lost (if it doesn't validate). This means the user won't be able to go back and edit previous fields. In my case, this isn't all that bad because the user may want to use the calculator over and over again with different values, so automatically deleting the input will save them a few steps. However, this may not be ideal in all cases.
It looks like Mobile Safari supports the new HTML5 input type attributes of email, number, search, tel, and url. These will switch the keyboard that is displayed. See the type attribute.
So for example, you could do this:
<input type="number" />
And when the input box has focus, the number keyboard is shown (as if the user had the full keyboard and hit the "123" button.
If you really only want numbers, you could specify:
<input type="tel" />
And then the user would get the phone number dialing keypad.
I know this works with Mobile Safari -- I only assume it will work with UIWebView.
http://conecode.com/news/2011/12/mobile-safari-uiwebview-input-types/
I made this little snippet to achieve what you want and I've tested it on iPhone 5 v7.0.3
I used e.which to read CharCode entered and then push it into an array (before) which represents digits before decimal mark and another array (after) to move values from (before) array past the decimal mark.
It might look complicated, due to my humble programming skills.
1) Code demo - 2) Currency conversion demo
HTML:
<input type="tel" id="number" />
JS
Variables and functions:
// declare variables
var i = 0,
before = [],
after = [],
value = [],
number = '';
// reset all values
function resetVal() {
i = 0;
before = [];
after = [];
value = [];
number = '';
$("#number").val("");
$(".amount").html("");
}
// add thousand separater
function addComma(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
Main code:
// listen to keyup event
$("#number").on("keyup", function (e, v) {
// accept numbers only (0-9)
if ((e.which >= 48) && (e.which <= 57)) {
// convert CharCode into a number
number = String.fromCharCode(e.which);
// hide value in input
$(this).val("");
// main array which holds all numbers
value.push(number);
// array of numbers before decimal mark
before.push(value[i]);
// move numbers past decimal mark
if (i > 1) {
after.push(value[i - 2]);
before.splice(0, 1);
}
// final value
var val_final = after.join("") + "." + before.join("");
// show value separated by comma(s)
$(this).val(addComma(val_final));
// update counter
i++;
// for demo
$(".amount").html(" " + $(this).val());
} else {
// reset values
resetVal();
}
});
Reset:
// clear arrays once clear btn is pressed
$(".ui-input-text .ui-input-clear").on("click", function () {
resetVal();
});
Result:
I think that you can use the same approach that I suggested to Ranjan.
Using a textfield like a buffer. First you need to detect when the keyboard appears and check if the first responder is the webview. Then you become a textview as the first responder.
When you are setting the text inside the input of the webview, you can add some logic to validate the number.
Here is a link of my example project with the solution, in your case you don't need change the inputView. But the approach is the same, use a Man in the middle.
Cant comment on https://stackoverflow.com/a/19998430/6437391 so posting as a separate answer...
This is the same idea as https://stackoverflow.com/a/19998430/6437391 but instead of switching the type, its the pattern that's switched.
This has the effect of not clearing the value on the textfield on focus when value does not match numeric format, for example, if the value has separators( 1,234.56 ).
$('input[type="text"]').on('touchstart', function() {
$(this).attr('pattern', '[0-9]*');
});
$('input[type="text"]').on('focus', function() {
$(this).attr('pattern', actualpattern);
});

Replacing text of input field moves its location

I have a search form that is controlled by some events, when it is blurred, the function checks to see if the value is blank, if it is, it puts the default search text back in place.
Here is a link to a sample page:
http://merkd.com/community
Here is the relevant function:
// searchInput is a jQuery reference to the <input> field
// searchTextColor is the original font color of the unfocused form
// searchText is the original search text
$('#header form').on('blur', 'input', function() {
searchInput.css('color', searchTextColor);
// When I comment these lines out, it doesn't move
if ( searchInput.val() == '' ) {
searchInput.val(searchText);
}
});
To see the glitch, type some text into the search field, then delete it and blur the search form, the input field will move to the left.
Any idea why this would be happening? Like I said, if I don't change the text then it doesn't move. I don't know how this would be affecting the position of the element within the page.
Problem
this is happen that's why the problem is occur
see in firebug
<input type="text" value="Search Teams, Players, Etc." name="search">
<img title="Search" alt="Search" src="/engine/themes/img/search.white.focus.png">
<input type="submit" value="Search Teams, Players, Etc.">
solution
$('#header form').on('blur', 'input[name=search]', function() {// not use input other wise valuse also set in submit input box
searchInput.css('color', searchTextColor);
// When I comment these lines out, it doesn't move
if ( $(this).val() == '' ) {
$(this).val(searchText);
}
});

Categories

Resources