I'm writing an app that runs on keyboard input but primarily as a barcode driven app. I'm having a hard time clearing some fields to reset the form after each button submission as well as refocusing on the correct field (the empty one)
Here's what it looks like
The Shipper ID doesn't clear unless I click that Black button or scan the barcode with value *CloseShipper*. It also loads empty the first time the page loads.
The Tracking # field clears and receives focus when I click the "Add To Batch" button or scan the barcode with value *AddToBatch*.
The App Barcode field clears immediately after I scan an App and adds it to an array that shows below it and receives focus right way to continue scanning non-stop until I finish the process by clicking or scanning the Add To Batch. (This part is working)
My problem is when I scan the *AddToBatch* barcode, nothing is happening. If I click it, the click event is being registered and it is clearing the fields that need to be cleared but the focus is still on the appbarcode. So, that's two problems separately.
Sorry I can't reproduce a working fiddle. Too many dependencies for it to work. So I'll post the relevant code here.
Template:
<form class="uk-form-horizontal uk-margin-medium barcodefields">
<div v-if="reset">
<div class="uk-margin">
<label
class="uk-form-label"
:for="_uid+'ctsinput'">
Shipper ID
</label>
<div class="uk-form-controls">
<input
class="uk-input"
:id="_uid+'ctsinput'"
name="shippernumber"
type="text"
maxlength="24"
:autofocus="'autofocus'"
v-focus
v-model.trim="shipperbarcode"
#input="runException"
/>
</div>
</div>
<div class="uk-margin">
<label
class="uk-form-label"
:for="_uid+'ctsinput'">
Tracking #
</label>
<div class="uk-form-controls">
<input
class="uk-input"
:id="trackingNumber"
name="trackingnumber"
type="text"
maxlength="24"
v-model.trim="trackingbarcode"
#input="runException"
/>
</div>
</div>
<div class="uk-margin">
<label
class="uk-form-label"
:for="_uid+'ctsinput'">
App. Barcode #
</label>
<div class="uk-form-controls">
<input
class="uk-input"
:id="_uid+'ctsinput'"
name="appbarcode"
type="text"
maxlength="24"
v-model.trim="applicationbarcode"
#change="addApplication"
/>
</div>
</div>
<!-- This is the list of apps scanned -->
<h5
v-if="this.appList.length !== 0"
class="heading-app-scanned"
>Applications Scanned In This Batch</h5>
<div
v-if="this.appList.length !== 0"
class="uk-card uk-card-secondary app-collection"
>
<div
v-for="appItem in appList"
:key="appItem.id"
class="app-scanned-item">
<div class="uk-padding-small">
<label class="uk-form-label">Application #:</label>
<span class="uk-text">{{appItem}}</span>
</div>
<div class="uk-divider"></div>
</div>
</div>
</div>
</form>
In my scripts, besides all props and data, etc, here is the logic part:
methods: {
...mapActions(["fetchBatches"]),
// evaluating the value of the shipperbarcode and trackingbarcode
runException: function(e) {
this.shipperbarcode = this.shipperbarcode.replace(/[^0-9.]/g, "");
this.trackingbarcode = this.trackingbarcode.replace(/[^0-9.]/g, "");
},
// evaluating what happens when an app is scanned
addApplication: function(e) {
let appBar = this.applicationbarcode;
if (
this.applicationbarcode === "*AddToBatch*" ||
this.applicationbarcode === "*CloseShipper*"
) {
this.applicationbarcode = "";
return;
} else {
this.counter += 1;
}
//give access to the add to batch function to trigger the modal window and close batch
this.addToBatch();
// send the qualifying barcodes to an array and clear the field for the next scan
this.appList.push(this.applicationbarcode);
//give focus to the tracking number after a batch has been made
document.addEventListener("change", function(appBar) {
if (appBar === "*AddToBatch*") {
this.appList = [];
this.shipperbarcode = document.querySelector(
"input[name=shippernumber]"
).value;
this.trackingbarcode = "";
let hasFocus = document.querySelector("input[name=trackingnumber]");
hasFocus.focus();
// after entering a new tracking number pass the focus to the barcode input
if (hasFocus.value.length > 0) {
hasFocus = document.querySelector("input[name=appbarcode]");
hasFocus.focus();
} else {
hasFocus = document.querySelector("input[name=trackingnumber]");
hasFocus.focus();
}
}
});
this.applicationbarcode = "";
this.applicationbarcode = this.applicationbarcode.replace(/[^0-9.]/g, "");
},
addedToBatch: function() {
this.addToBatch("*AddToBatch*");
},
// When the add to batch button is scanned
addToBatch: function(appBar) {
// open the modal if the counter is above 25. This will be rewritten to read from server as the 25 can differ
if (this.counter >= 25) {
UIkit.modal("#closeBatchDialog").show();
}
// if the counter is > 0 show the close batch button
if (this.counter > 0) {
this.finishBatch = true;
}
// If the app barcode is Add to Batch barcode give shipper # input field the value it already has
// and clear the tracking number field. ********** Must exist for click event
if (appBar === "*AddToBatch*") {
this.appList = [];
this.shipperbarcode = document.querySelector(
"input[name=shippernumber]"
).value;
this.trackingbarcode = "";
//give focus to the tracking number after a batch has been made
let hasFocus = document.querySelector("input[name=trackingnumber]");
hasFocus.focus();
// after entering a new tracking number pass the focus to the barcode input
if (hasFocus.value.length > 0) {
hasFocus = document.querySelector("input[name=appbarcode]");
hasFocus.focus();
} else {
hasFocus = document.querySelector("input[name=trackingnumber]");
hasFocus.focus();
}
}
},
// if the close shipper barcode is scanned
closeShipper: function(e) {
// if the barcode for close shipper is scanned
if (this.applicationbarcode === "*CloseShipper*") {
// clear all fields
this.appList = [];
this.shipperbarcode = "";
this.trackingbarcode = "";
// give the shipper id field focus
document.addEventListener("change", function() {
let hasFocus = document.querySelector("input[name=shippernumber]");
hasFocus.focus();
});
}
},
sendFocus: function(e) {
document.addEventListener("keydown", function(e) {
var input = e.target.nodeName.toLowerCase() === "input";
var form = e.target.form;
if (e.key === "Enter" && input) {
var index = Array.prototype.indexOf.call(form, e.target);
form.elements[index + 1].focus();
}
});
}
},
created() {
let that = this;
this.fetchBatches().then(function() {
that.sendFocus();
});
}
I commented as much as I could. The addApplication method is the one that validates that the barcode is a number or AddToBatch. If it's a number barcode, push it to the array as it is recognized as a normal barcode format. If it's reading AddToBatch, then clear the array (which later will put the array to the API), clear the tracking field and send the cursor to the tracking field to read a new tracking number
Any help will be very appreciated. I'm the only one here in this particular skillset and that sucks :( Thanks
P.S. No jQuery. ES6 preferably.
You have an empty return inside application, thats why it behaves wierd on "AddToBatch" condition, did you missed anything inside if condition or conditon should be like
this.applicationbarcode === "AddToBatch" && this.applicationbarcode === "CloseShipper"
if (
this.applicationbarcode === "*AddToBatch*" ||
this.applicationbarcode === "*CloseShipper*"
) {
this.applicationbarcode = "";
return;
} else {
this.counter += 1;
}
Related
I'm new to coding and I was wondering how to correct the following code.
Basically, I want to save the user's scanned input to a variable and display it as a prepend. Also If possible being able to scan multiple scans while it just adds it to another variable so I can export the variables. Something like this when its exported as a .txt file
testscan1
tesstscan2
ABCDEF
var string = "";
let inputStart, inputStop;
$("#scanInput")[0].onpaste = e => e.preventDefault();
// handle a key value being entered by either keyboard or scanner
var lastInput
let checkValidity = () => {
if ($("#scanInput").val().length < 8) {
$("#scanInput").val('');
} else {
$("body").append()
}
timeout = false
}
let timeout = false
$("#scanInput").keypress(function(e) {
if (performance.now() - lastInput > 50) {
$("#scanInput").val('')
}
lastInput = performance.now();
if (!timeout) {
timeout = setTimeout(checkValidity, 200)
}
});
<form autocomplete="off" onsubmit="return false">
<br>
<input type="text" name="serial" placeholder="Please scan laptop Barcode" id="scanInput" />
</form>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
I'm brand new to coding. I've created a form with three fields- two with "number" types and one with radio button selection. I'm trying to utilize "try catch throw" to validate these fields and have error messages echoed onto the screen (not as an alert). I know that there is a lot of code in here, but I am really lost with this. Here is my HTML and js:
HTML:
<form>
<fieldset>
<label for="hshld" class="formhdr">Total number of people in your household:</label>
<input type="number" id="hshld" name="hshld" min="1">
</fieldset>
<fieldset>
<label for="hrrisk" class="formhdr">Number of high-risk people in your household:</label>
<input type="number" id="hrrisk" name="hrrisk" min="0">
</fieldset>
<fieldset>
<legend class="formhdr">Number of weeks in isolation:</legend>
<input type="radio" id="countone" name="headcount">
<label for="countone" class="numweeks">1</label>
<input type="radio" id="counttwo" name="headcount">
<label for="counttwo" class="numweeks">2</label>
<input type="radio" id="countthree" name="headcount">
<label for="countthree" class="numweeks">3</label>
<input type="radio" id="countfour" name="headcount">
<label for="countfour" class="numweeks">4+</label>
</fieldset>
<input type="submit" value="Submit" id="submit">
</form>
and my .js:
//Global variables
var hshld = document.getElementById("hshld");
var mysubmit = document.getElementById("submit");
var radioError = document.getElementById("radioError");
var weekCount;
//this function checks to see if the user entered a number into the field
function validatehshld() {
try {
if (hshld.value == "") {
throw "Enter a number!";
}
hshld.style.outline = "none";
// clear input box
}
catch (hshldError) {
hshld.style.outline = "2.5px dashed red";
hshld.placeholder = hshldError;
return false;
}
}
// makes sure that the radio button is selected. If not, throws an error message into the "radioError" paragraph at under the form.
function validatewkCount() {
try {
if (weekCount == 0) {
throw document.getElementById('radioError').innerHTML = "Select a number!";
}
// clear input box
hshld.style.outline = "none";
}
catch (weekCountError) {
radioError.style.outline = "2.5px dashed red";
radioError.placeholder = radioError;
return false;
}
}
// stop the form from submitting if a field needs attention
function endEvent() {
return event.preventDefault();
}
function validateSubmit() {
if(validatehshld() === false && validatewkCount() === false) {
endEvent();
}
}
// EventListeners, includes IE8 compatibility
if (hshld.addEventListener) {
hshld.addEventListener("focusout", validatehshld, false);
} else if (hshld.attachEvent) {
hshld.attachEvent("onclick", validatehshld);
}
// runs validateSubmit() function when the user clicks the submit button
if (mysubmit.addEventListener) {
mysubmit.addEventListener("click", validateSubmit, false);
} else if (mysubmit.attachEvent) {
mysubmit.attachEvent("onclick", validateSubmit);
}
if (mysubmit.addEventListener) {
mysubmit.addEventListener("click", numBottles, false);
} else if (mysubmit.attachEvent) {
mysubmit.attachEvent("onclick", numBottles);
}
// this function gets called via the onclick attribute (line 44)
function numBottles() {
// takes the current value of the input field from id "hshld"
var people = document.getElementById("hshld").value;
var hrrisk = document.getElementById("hrrisk").value;
// this variable represents the number of gallons a single person should have for one week of isolation- 1 gallon per day
var weekWater = 7;
// this variable will hold the number of weeks selected from the radio buttons
var weekCount;
// this code determines which radio button is selected and assigns a value to the variable depending on which radio button is selected
if (document.getElementById('countone').checked) {
var weekCount = 1;
} else if (document.getElementById('counttwo').checked) {
var weekCount = 2;
} else if (document.getElementById('countthree').checked) {
var weekCount = 3;
} else if (document.getElementById('countfour').checked) {
var weekCount = 4;
} else if (isNaN(weekCount) === true) {
var weekCount = 0;
}
// echo out the calculation (people X weekWater) to the span object with id=bottles
document.getElementById("bottles").innerHTML = (people * weekWater * weekCount) + (hrrisk * weekCount);
}
Try not to use try, catch, or throw here, instead create your error message in a new element and place it in the html somewhere you think it looks nice.
I would just use:
if (typeof hshld.value !== 'number') { // if a wrong data type was entered
document.getElementById("error-zone").innerHTML += "<div>Enter a number!</div"
} else {
// continue calculating answer
}
for the quick and dirty method.
I'm building a multipage form and I have some unusual validation requirements. Here's what I'd like to do/what I have done so far.
What I Want to Do:
(1) As each form field is filled in, I want a function to run and check that the user-input has met certain conditions -- i.e. for first and last name, that there are no numbers and there is a space in between the names.
(2) Once each of the field are full and have passed as true, I want another function to run that re-enabled a previously disabled "Next" button that will move the user to the next page of the form.
What I Have Done
(1) Created a mini version of the form with two inputs:
One that takes a first name, a space and a last name
One that takes a phone number set up the following way xxx xxx xxx
(2) I've console.logged the results with pass/fail logic so I know when certain things are being input by the user, that the code is validating properly.
Where I am Stuck:
I do not know how to create the secondary code that will reenabled the previously disabled "next" button that will move the form to the next page.
What I would like to do is make it so when the "Next" button is reenabled, and clicked on, it's own onclick function hides the current page, looks for the next page in the sequence and changes its display:block and I believe I have that code worked out separately, but I don't know how to integrate it with my other needs.
function checkForm()
{
var firstName = document.getElementById("name").value;
var phone = document.getElementById("phone").value;
function checkFirstName()
{
if(firstName == "" || !isNaN(firstName) || !firstName.match(/^[A-Za-z]*\s{1}[A-Za-z]*$/))
{
console.log("Put a first Name and Last Name");
}
else
{
console.log("Thank You");
}
};
checkFirstName();
function checkPhoneNumber()
{
if(!phone.match(/^[0-9]*\s{1}[0-9]*\s{1}[0-9]*$/))
{
console.log("Please Put in a proper phone number");
}
else
{
console.log("Thank you");
cansubmit = true;
}
};
checkPhoneNumber();
};
<form>
First Name: <input type="text" id="name" onblur="checkForm()" /><label id="nameErrorPrompt"></label>
<br />
Phone Number: <input type="text" id="phone" onblur="checkForm()" /><label></label>
<br />
<button id="myButton" disabled="disabled">Test Me</button>
</form>
See below code.
It might be more user-friendly to use on keyup rather than onblur, as most users I know will try and click the disabled button, rather than pressing tab or focusing on another element.
function checkForm() {
var firstName = document.getElementById("name").value;
var phone = document.getElementById("phone").value;
var phoneCanSubmit, nameCanSubmit = false;
function checkFirstName() {
if (firstName == "" || !isNaN(firstName) || !firstName.match(/^[A-Za-z]*\s{1}[A-Za-z]*$/)) {
nameCanSubmit = false;
console.log("Put a first Name and Last Name");
} else {
nameCanSubmit = true;
console.log("Thank You");
}
};
checkFirstName();
function checkPhoneNumber() {
if (!phone.match(/^[0-9]*\s{1}[0-9]*\s{1}[0-9]*$/)) {
phoneCanSubmit = false;
console.log("Please Put in a proper phone number");
} else {
phoneCanSubmit = true;
console.log("Thank you");
cansubmit = true;
}
};
checkPhoneNumber();
if (nameCanSubmit && phoneCanSubmit) {
document.getElementById("myButton").disabled = false;
} else {
document.getElementById("myButton").disabled = true;
}
};
<form>
First Name:
<input type="text" id="name" onblur="checkForm()" />
<label id="nameErrorPrompt"></label>
<br />Phone Number:
<input type="text" id="phone" onblur="checkForm()" />
<label></label>
<br />
<button id="myButton" disabled="disabled">Test Me</button>
</form>
The code below gives you what you want. I removed some extraneous checks to simplify the code and also moved the event handlers from he HTML to the JavaScript. I also pulled the field checks out of the larger checkForm function. This provides you the flexibility to use them one at at time if need be.
window.addEventListener('load', function(e) {
var nameInput = document.getElementById('name');
var phoneInput = document.getElementById('phone');
var myButton = document.getElementById('myButton');
myButton.addEventListener('click', function(e) {
e.preventDefault(); //Stop the page from refreshing
getNextPage('Next page shown!!');
}, false);
nameInput.addEventListener('blur', function(e) {
checkName(this.value);
}, false);
phoneInput.addEventListener('blur', function(e) {
//Uncomment below to make this responsible only for checking the phone input
//checkPhoneNumber(this.value);
/*You could do away with diasbling and check the form
on submit, but if you want to keep the disable logic
check the whole form on the blur of the last item*/
checkForm();
}, false);
}, false);
function getNextPage(foo) {
console.log('Callback fired: ', foo);
//Do something here
}
function checkPhoneNumber(phone) {
if(!phone.match(/^[0-9]*\s{1}[0-9]*\s{1}[0-9]*$/)) {
console.log("Please Put in a proper phone number");
return 0;
}
else {
console.log("Thank you name entered");
return 1;
}
};
//Removed a bit of over coding, no ned to check isNaN or empty string since using regex already
function checkName(firstAndLastName) {
if(!firstAndLastName.match(/^[A-Za-z]*\s{1}[A-Za-z]*$/)) {
console.log("Put a first Name and Last Name");
return 0;
}
else {
console.log("Thank You phone entered");
return 1;
}
};
function checkForm() {
var validCount = 0;
fieldCount = document.forms[0].elements.length - 1; //substract one for the submitbutton!
var phoneNum = document.getElementById('phone').value;
var name = document.getElementById('name').value;
var myButton = document.getElementById('myButton');
validCount += checkPhoneNumber(phoneNum);
validCount += checkName(name);
console.log(validCount + ' of ' + fieldCount + ' fields are valid');
if (validCount > 0 && validCount === fieldCount) {//Compare the inputs to the number of valid inputs
myButton.disabled = false;
}
else {
myButton.disabled = true;
}
}
HTML
<form>
First Name: <input type="text" id="name" /><label id="nameErrorPrompt"></label>
<br />
Phone Number: <input type="text" id="phone" /><label></label>
<br />
<button id="myButton" disabled="disabled">Test Me</button>
</form>
How about you start by making the onblur for each input return a boolean indicating if the field is valid.
Then setting a cansubmit variable (= checkName && checkPhone) in the checkForm function and only moving on after that - then you don't need to enable and disable the button.
If you really want the button to enable you can use the same pattern, but do
document.getElementById("myButton").disabled = !canSubmit;
and you will always want to call checkForm on field blur like you are now.
Also note you aren't scoping canSubmit locally right now.
I want to allow users to see what they type in a password field. For instance, as soon as they type a letter in the field, they should see what was typed and the letter should change back to its default bullet.
This jQuery plugin does what you want: https://code.google.com/archive/p/dpassword/
The blog post contains the details.
Another option is to swap the type of the field using a checkbox ("Show password?"). Switching the type of the input element between text and password should achieve this. If that doesn't work, you need to create a new input element and copy the value.
Note on security: The password is hidden for a reason. Just to give you an idea of the possible attacks, here is the ones I know of:
If a smart phone is lying on the table next to your keyboard, then the vibrations caused by typing can be recorded and the keys you pressed can be calculated from that.
If the monitor is visible from outside the building, a good telescope can read you screen over quite a distance. If you wear glasses or there is a teapot, you can still read that at 30m.
So be aware that displaying a password does compromise security.
Related articles:
I Spy Your PC: Researchers Find New Ways to Steal Data
http://css-tricks.com/better-password-inputs-iphone-style/
Building uppon #SubhamBaranwal's answer that has the major drawback of losing the password field's value, you could do something like the following:
$(_e => {
const frm = $('#my-form');
const passField = frm.find('.pass');
const passCopy = $('<input type="hidden" />');
passCopy.prop('name', passField.prop('name'));
passField.prop('name', null);
passField.prop('type', 'text');
frm.append(passCopy);
let timer;
passField.on("keyup", function(e) {
if (timer) {
clearTimeout(timer);
timer = undefined;
}
timer = setTimeout(function() {
copyPass();
passField.val(createBullets(passField.val().length));
}, 200);
});
function createBullets(n) {
let bullets = "";
for (let i = 0; i < n; i++) {
bullets += "•";
}
return bullets;
}
function copyPass() {
const oPass = passCopy.val();
const nPass = passField.val();
if (nPass.length < oPass.length) {
passCopy.val(oPass.substr(0, nPass.length));
} else if (nPass.length > oPass.length) {
passCopy.val(oPass + nPass.substr(oPass.length));
}
}
/* for testing */
frm.append('<input type="submit" value="Check value" />');
frm.on('submit', e => {
e.preventDefault();
copyPass();
alert(passCopy.val() || "No Value !");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="my-form">
<input class="pass" type="password" name="pass" />
</form>
However, this remains a simplistic implementation that will only support editing the password from the end (appending characters or backspaces). For a full implementation, you'd have to check and record where the current selection lies at each keyUp, and then modify the recorded value according to what you get after the input field was updated. Far more complicated
I think you want something like this JSFiddle
HTML Code -
<input class="pass" type="password" name="pass" />
JS Code -
function createBullets(n) {
var bullets = "";
for (var i = 0; i < n; i++) {
bullets += "•";
}
return bullets;
}
$(document).ready(function() {
var timer = "";
$(".pass").attr("type", "text").removeAttr("name");
$("body").on("keyup", ".pass", function(e) {
clearTimeout(timer);
timer = setTimeout(function() {
$(".pass").val(createBullets($(".pass").val().length));
}, 200);
});
});
I have a grid of buttons which the user can select. What happens is the user enters in the text box the number of buttons they want to select and then they select those buttons in the grid. For example if the user types in "2" in the text box and selects "2" buttons and then tries to select a third, then an alert box appears stating that user is beyond limit please deselect a button.
Now what I want to know is how do I code it so that if user selects less number of buttons than in the text box, then an alert message appears stating to select more buttons?
Thanks
Code in jsfiddle: click here
Well, in order not to be showing an alert every time the user selects a button and it happens to be less than the amount of buttons he/she selected, you'll want to add some sort of submit button and ONLY have a script check the circumstances when they click it.
<form onsubmit="validate.submit(); return false;">
<textarea id="input"></textarea>
<input type="submit" value="Submit" />
</form>
Simple enough, correct? Lets add DIV for where the buttons appear.
<form id="form" onsubmit="validate.submit(); return false;">
<textarea id="input"></textarea> <br />
<div id="buttons"></div> <hr />
<input type="submit" value="Submit" />
</form>
Now lets setup the JavaScript Functionality.
window.validate = ({
config: {
min: 1, // Minimum amount of buttons allowed.
max: 10 // Maximum amount of buttons allowed.
},
data: {
state: 0,
input: null,
buttons: null,
form: null
},
validate: function(refer) {
// Refer is the amount of check boxes checked.
if(refer < this.config.min)
{
alert("You checked to little!");
}
else if(refer > this.config.max)
{
alert("You checked to much!");
}
else
{
alert("You checked JUST right!");
}
},
submit: function() {
if(this.data.state === 1)
{
var refers = this.data.form.val,
refer = 1;
if(Object.prototype.toString.call(refers) === "[object Array]")
{
refer = refers.length;
}
this.validation(refer);
return refer;
}
else
{
this.data.state = 0;
try {
var q = this.data.input.value;
// Use Number object incase of cases where numbers have non-digit,
// characters, like Infinity, NaN, 1e+10, ect.
if(new Number(q).valueOf() === 0 && q.match(/\D/)) { throw new Error(); }
q = eval(q);
if(q > this.config.max)
{
alert("We cannot process that many buttons!");
}
else if(q < this.config.min)
{
alert("You must have at least " + this.config.min + " buttons!");
}
else
{
q = Math.abs(q); // Negative to positive integer.
// Textarea validation complete!
var html = "";
for(var i=q; i>0; i--)
{
html = html + "<input type=\"checkbox\" name=\"val\" />";
}
this.data.buttons.innerHTML = html;
this.data.state = 1;
}
} catch(e) {
alert("You didn't enter a valid Number!");
}
}
},
setup: function() {
window.onload = (function() {
validate.data.form = document.getElementById("form");
validate.data.input = document.getElementById("input");
validate.data.buttons = document.getElementById("buttons");
});
delete this.setup;
return this;
}
}).setup();
This was a quick a dirty example. You might have a few errors, for I didn't test it. Good luck! :D