I have a object named MYMODCLASS that contains all my module functions. One of these functions addNumberValues(id, getId) loops through a collection of number inputs using the getElementsByName method and adds the values to check that the values are less than 100.
When I invoke the function using the following notation:
window.onload = document.getElementsByName('grade').oninput = MYMODCLASS.addNumberValues('info', 'grade');
The function only fires once when the document loaded, but not again.
When I invoke it as a parameter to an input element is works consistently:
<input type="number" value=0 id="ind" name="grade" min="0" max="100" oninput="MYMODCLASS.addNumberValues('info', 'grade')" required>
<input type="number" value=0 id="nv" name="grade" min="0" max="100" oninput="MYMODCLASS.addNumberValues('info', 'grade')" required>
The problem with the latter invocation is that I have to repeat the oninput parameter 30 times. Therefore, I want to use the former invocation for the ``addNumberValues function.
MYMODCLASS.addNumberValues = function (id, getId) {
var element = document.getElementById(id);
var el = document.getElementsByName(getId);
var i = 0;
el.forEach((ite) => {
console.log(ite.value);
if (!isNaN(parseFloat(ite.value)) && isFinite(ite.value)) {
if (i === 0) {
i = parseFloat(ite.value);
} else {
i = parseFloat(i) + parseFloat(ite.value);
}
}
})
console.log(i);
if (i > 100 || i < 0) {
element.className = 'lbwarn';
element.innerText = i;
alert("Grade exceeds 100!")
} else {
element.className = 'lbinfo';
element.innerText = i;
}
};
Edit
So after reading the comments I decided to create a loop that sets the function for each individual element by id. But this is still not working.
window.onload = function() {
var numel = document.getElementsByName('grade');
numel.forEach((p) => {
console.log(p.id);
document.getElementById(p.id).oninput = MYMODCLASS.addNumberValues('info', 'grade');
})
}
How can I get the invocation to work consistently using my last method?
Related
I have an input where the user can enter initials. The input has a max length of 3.
I have the following js
personaliseShirt.plInitials = function () {
console.log('pressed');
var inputPL = $('.max-length_3');
$(inputPL).on('keyup', function () {
var max = 3;
console.log(inputPL.val.length);
if (inputPL.val.length > max) {
inputPL.val = inputPL.value.substring(0, max);
}
})
}
My issue is that the first input field seems to stop the user from entering more than 3 characters but if the user has multiple, then after the first input the rest allow for more than 3 :/
HTML for input field
<input onkeyup="this.value = this.value.toUpperCase();" pattern="[A-Za-z]+" maxlength="3" type="text" class="form-control input-block-level defaultY? max-length_3" max="3" value="" placeholder="Enter Player Initials" name="player_2_9_6" id="player_2_9_6">
Any help or suggestions would be great
Thanks in advance!
Your variable inputPL is a JQuery array with multiple elements in it. In your keyup handler, you check for the length of this array, which won't work. Use this instead:
personaliseShirt.plInitials = function () {
console.log('pressed');
var inputPL = $('.max-length_3');
$(inputPL).on('keyup', function () {
var max = 3;
var $thisElem = $(this);
console.log($thisElem.val.length);
if ($thisElem.val.length > max) {
$thisElem.val = $thisElem.value.substring(0, max);
}
})
}
Also please check, if your mix-up of val and value is intended, or if you need to use val() instead.
It's working on firefox and chrome. You can use this function for repeated use.
$('input.testinput').on('keyup', function() {
limitText(this, 3)
});
function limitText(field, maxChar){
var ref = $(field),
val = ref.val();
if ( val.length >= maxChar ){
ref.val(function() {
console.log(val.substr(0, maxChar))
return val.substr(0, maxChar);
});
}
}
Demo
I am trying to use a set of range sliders to impact each other in various ways. My If the statement is working correctly the first time I change a value, but the second time I change a value, it is adding the entire value instead of the change.
I've tried everything I know so far on how to resolve this, but breaks and continues do not seem to be fixing the problem.
<form>
<Label for="sliderBarOne">Ready</Label>
<input type="range" id="sliderBarOne" min="0" max="100" step="0.01" value="0" onchange="this.form.rangeOne.value=this.value">
<input type="number" id="rangeOne" value="0" onchange="this.form.sliderBarOne.value=this.value">
<br>
<Label for="sliderBarTwo">ACW</Label>
<input type="range" id="sliderBarTwo" min="0" max="100" step="0.01" value="0" onchange="this.form.rangeTwo.value=this.value">
<input type="number" id="rangeTwo" value="0" onchange="this.form.sliderBarTwo.value=this.value">
<br>
<Label for="sliderBarThree">Extra</Label>
<input type="range" id="sliderBarThree" min="0" max="100" step="0.01" value="0" onchange="this.form.rangeThree.value=this.value">
<input type="number" id="rangeThree" value="0" onchange="this.form.sliderBarThree.value=this.value">
<br>Sum: <span id="sum">0</span>
</form>
<script>
document.getElementById("sliderBarOne").addEventListener("change", updateReady);
document.getElementById("sliderBarTwo").addEventListener("change", updateACW);
document.getElementById("sliderBarThree").addEventListener("change", updateExtra);
document.getElementById("rangeOne").addEventListener("change", updateReady);
document.getElementById("rangeTwo").addEventListener("change", updateACW);
document.getElementById("rangeThree").addEventListener("change", updateExtra);
function updateReady() {
var readyBox = document.getElementById('sliderBarOne');
var acwBox = document.getElementById('sliderBarTwo');
var extraBox = document.getElementById('sliderBarThree');
var readyField = document.getElementById('rangeOne');
var acwField = document.getElementById('rangeTwo');
if (readyBox.value < 100 || readyField.value < 100) {
acwBox.value = 100 - parseFloat(readyBox.value);
//Set Slider Values Into Fields
readyField.value = readyBox.value;
acwField.value = acwBox.value;
extraField.value = extraBox.value;
}
updateSum();
}
function updateACW() {
var readyBox = document.getElementById('sliderBarOne');
var acwBox = document.getElementById('sliderBarTwo');
var extraBox = document.getElementById('sliderBarThree');
updateSum();
}
function updateExtra() {
var readyBox = document.getElementById('sliderBarOne');
var acwBox = document.getElementById('sliderBarTwo');
var extraBox = document.getElementById('sliderBarThree');
var readyField = document.getElementById('rangeOne');
var acwField = document.getElementById('rangeTwo');
var extraField = document.getElementById('rangeThree');
if (extraBox.value > 0 || extraField.value > 0) {
readyBox.value = parseFloat(readyBox.value) - parseFloat(extraBox.value);
acwBox.value = parseFloat(acwBox.value) + parseFloat(extraBox.value);
//Set Slider Values Into Fields
readyField.value = readyBox.value;
acwField.value = acwBox.value;
extraField.value = extraBox.value;
}
updateSum();
}
</script>
The first time I enter a value into Ready, it properly subtracts that value from 100 to provide ACW.
Then, when I put a value into Extra, it accurately subtracts that value from Ready and adds to ACW. For instance, Ready 95, ACW 5. Making Extra 1 makes Ready 94 and ACW 6. The problem is, when I change Extra to 2, it makes Ready 92 and ACW 8 instead of Ready 93 and ACW 7.
I'm not sure how to grab the change in the value on each change.
your updatesum() is not defined and your extrafield is not defined in updateready() function
Because the values are changed before. You first change them by 1, and then change them by 2. Hence, it means the extra is 3! Unless you reload the page to reinitialize the values to 95 and 6 and then apply extra 2. It will give you 93 and 7.
To solve the problem you can write an initialize function that initializes the values, and then call the function at the first line of the updateExtra function.
OmG provided the inspiration to create an initial value field. So, I adjusted the code as follows. Thanks OmG!
function updateExtra() {
var readyBox = document.getElementById('sliderBarOne');
var acwBox = document.getElementById('sliderBarTwo');
var extraBox = document.getElementById('sliderBarThree');
var readyField = document.getElementById('rangeOne');
var acwField = document.getElementById('rangeTwo');
var extraField = document.getElementById('rangeThree');
var initialReady = document.getElementById('initialReady');
var initialACW = document.getElementById('initialACW');
if (extraBox.value > 0 || extraField.value > 0) {
readyBox.value = parseFloat(initialReady.value) - parseFloat(extraBox.value);
acwBox.value = parseFloat(initialACW.value) + parseFloat(extraBox.value);
//Set Slider Values Into Fields
readyField.value = readyBox.value;
acwField.value = acwBox.value;
extraField.value = extraBox.value;
}
updateSum();
}
window.onload = function init() {
console.log("DOM is ready!");
var input, value;
input = document.getElementById("yourGuess");
input = input.value;
input.addEventListener("checking", check, false);
check(value);
}
function check(value) {
if(input < 0 && input > 10) {
alert("The number must be between 0 - 10");
value = 0;
}
}
<label for="yourGuess">You choose: </label>
<input id="yourGuess" type="number" min="0" max="10">
I can't find any solution anywhere that correspond to the issue above.
So I have a number type input and declared a min and max attribute with the value 0 and 10 respectively.
The user can click the input field and change its value outside of range, hence I need to use javasricpt to check any changes made
You're overwritting your HTMLInputElement with the value which is string, hence you're getting error.
Use onchange event along with document.addEventListener.
I've DOMContentLoaded method which gives you better idea instead of using window.onload!
document.addEventListener('DOMContentLoaded',function() {
document.querySelector("#yourGuess").onchange=check;
},false);
function check(event) {
if(event.target.value > 10 || event.target.value < 0){
alert("The number must be between 0 - 10");
event.target.value = 0;
}
}
<label for="yourGuess">You choose: </label>
<input id="yourGuess" type="number" min="0" max="10">
Multiple issues in your code
You are setting input to the input.value so input becomes a String which doesn't have addEventListener
Use change event instead of checking.
check method doesn't have visibility to input, so rely on event.target.
Your if condition needs an OR || instead of &&
Demo
window.onload = function init() {
console.log("DOM is ready!");
var input = document.getElementById("yourGuess");
input.addEventListener("change", check, false);
}
function check ( event )
{
var input = Number(event.target.value);
console.log(input);
if(input < 0 || input > 10) {
alert("The number must be between 0 - 10");
value = 0;
}
}
<label for="yourGuess">You choose: </label>
<input id="yourGuess" type="number" min="0" max="10">
function change(){
var num = document.getElementById("num").value;
if(num > 10 || num < 0){
alert("Number is not in range");
}
}
<input id="num" type="number" min="0" max="10" onchange="change()">
if you type number manually then you should left that input field to check or you can use other methods such as onkeypress etc.
You are setting addeventlistener to the input value.
You are trying to use input in check function but it is not available in that method as it is not defined in the scope of that function.
window.onload = function init() {
console.log("DOM is ready!");
var value;
var input = document.getElementById("yourGuess");
value = input.value;
input.addEventListener("change",check)
}
function check() {
if(this.value < 0 || this.value > 10) {
alert("The number must be between 0 - 10");
value = 0;
}
}
<label for="yourGuess">You choose: </label>
<input id="yourGuess" type="number" min="0" max="10">
I cannot see where I am going wrong with this. My code is...
function firstC()
{
var x = document.getElementsByClassName("uValue");
for(var i = 0; i < x.length; i++) {
x.value.charAt(0).toUpperCase();
}
}
It is called by...
<td><input type="text" name="firstname" value="(required)" id="firstName" class="uValue" onclick="empty(this.id)" onblur="firstC()" /></td>
The empty() function works correctly by removing the value of the input box if its value is "(required)", but I cannot get the firstC() function to capitalise the first character of any input.
EDIT: I am using getElementsByClassName as there are multiple input boxes which I am trying to allow to use the same function.
You forgot to assign the value back
function firstC()
{
var x = document.getElementsByClassName("uValue");
for(var i = 0; i < x.length; i++) {
x[i].value = x[i].value.charAt(0).toUpperCase() + x[i].value.substr(1);
}
}
You should instead pass the this into your inline JS eventers:
onclick="empty(this)" onblur="firstC(this)"
Example
function empty(el) { // el now refers to the this referrer
el.value="";
}
function firstC(el) {
var val = el.value;
el.value = val.charAt(0).toUpperCase() + val.substr(1);
}
<input type="text" onclick="empty(this)" onblur="firstC(this)" value="(required)" id="firstName" class="uValue" name="firstname">
P.S: don't forget that instead of using empty() and value="(required)" you can simply use the placeholder attribute
placeholder="(required)"
I've got a form on my site using 6 input fields. The site visitor simply enters a 6 digit code into these 6 boxes. The thing is that they'll get the 6 digit code and it would be ideal to allow them to simply copy the 6 digit code we send them into these input fields by simply putting pasting into the first input field and having the remaining 5 digits go into the remaining 5 input fields. It would just make it much easier than having to manually enter each digit into each input field.
Here's the code we're currently using, but it can easily be changed to accomplish what is described above:
<input type="text" maxlength="1" class="def-txt-input" name="chars[1]">
<input type="text" maxlength="1" class="def-txt-input" name="chars[2]">
<input type="text" maxlength="1" class="def-txt-input" name="chars[3]">
<input type="text" maxlength="1" class="def-txt-input" name="chars[4]">
<input type="text" maxlength="1" class="def-txt-input" name="chars[5]">
<input type="text" maxlength="1" class="def-txt-input" name="chars[6]">
I saw a posting similar to this here: Pasting of serialnumber over multiple textfields
But it doesn't have the solution I'm looking for. Ideally this could be pulled off using jQuery or plain JavaScript.
Edit
I didn't like the timer solution I used in the paste event and the complexity of just using the input or paste event.
After looking at this for a while I added a solution which uses a hybrid between the 2.
The code seems to do all that is required now.
The Script:
var $inputs = $(".def-txt-input");
var intRegex = /^\d+$/;
// Prevents user from manually entering non-digits.
$inputs.on("input.fromManual", function(){
if(!intRegex.test($(this).val())){
$(this).val("");
}
});
// Prevents pasting non-digits and if value is 6 characters long will parse each character into an individual box.
$inputs.on("paste", function() {
var $this = $(this);
var originalValue = $this.val();
$this.val("");
$this.one("input.fromPaste", function(){
$currentInputBox = $(this);
var pastedValue = $currentInputBox.val();
if (pastedValue.length == 6 && intRegex.test(pastedValue)) {
pasteValues(pastedValue);
}
else {
$this.val(originalValue);
}
$inputs.attr("maxlength", 1);
});
$inputs.attr("maxlength", 6);
});
// Parses the individual digits into the individual boxes.
function pasteValues(element) {
var values = element.split("");
$(values).each(function(index) {
var $inputBox = $('.def-txt-input[name="chars[' + (index + 1) + ']"]');
$inputBox.val(values[index])
});
};
See DEMO
Here is an example of a jquery plugin that does the same thing as the original answer only generalized.
I went to great lengths to modify the original answer ( http://jsfiddle.net/D7jVR/ ) to a jquery plugin and the source code is here: https://github.com/relipse/jquery-pastehopacross/blob/master/jquery.pastehopacross.js
An example of this on jsfiddle is here:
http://jsfiddle.net/D7jVR/111/
The source as of 4-Apr-2013 is below:
/**
* PasteHopAcross jquery plugin
* Paste across multiple inputs plugin,
* inspired by http://jsfiddle.net/D7jVR/
*/
(function ($) {
jQuery.fn.pastehopacross = function(opts){
if (!opts){ opts = {} }
if (!opts.regexRemove){
opts.regexRemove = false;
}
if (!opts.inputs){
opts.inputs = [];
}
if (opts.inputs.length == 0){
//return
return $(this);
}
if (!opts.first_maxlength){
opts.first_maxlength = $(this).attr('maxlength');
if (!opts.first_maxlength){
return $(this);
}
}
$(this).on('paste', function(){
//remove maxlength attribute
$(this).removeAttr('maxlength');
$(this).one("input.fromPaste", function(){
var $firstBox = $(this);
var pastedValue = $(this).val();
if (opts.regexRemove){
pastedValue = pastedValue.replace(opts.regexRemove, "");
}
var str_pv = pastedValue;
$(opts.inputs).each(function(){
var pv = str_pv.split('');
var maxlength;
if ($firstBox.get(0) == this){
maxlength = opts.first_maxlength;
}else{
maxlength = $(this).attr('maxlength');
}
if (maxlength == undefined){
//paste them all!
maxlength = pv.length;
}
//clear the value
$(this).val('');
var nwval = '';
for (var i = 0; i < maxlength; ++i){
if (typeof(pv[i]) != 'undefined'){
nwval += pv[i];
}
}
$(this).val(nwval);
//remove everything from earlier
str_pv = str_pv.substring(maxlength);
});
//restore maxlength attribute
$(this).attr('maxlength', opts.first_maxlength);
});
});
return $(this);
}
})(jQuery);
This shouldn't be too difficult ... add a handler for the paste event on the first input, and then process per the requirement.
Edit
Actually this is much trickier than I thought, because it seems there's no way to get what text was pasted. You might have to kind of hack this functionality in, using something like this (semi-working)... (see the JSFiddle).
$(document).on("input", "input[name^=chars]", function(e) {
// get the text entered
var text = $(this).val();
// if 6 characters were entered, place one in each of the input textboxes
if (text.length == 6) {
for (i=1 ; i<=text.length ; i++) {
$("input[name^=chars]").eq(i-1).val(text[i-1]);
}
}
// otherwise, make sure a maximum of 1 character can be entered
else if (text.length > 1) {
$(this).val(text[0]);
}
});
HTML
<input id="input-1" maxlength="1" type="number" />
<input id="input-2" maxlength="1" type="number" />
<input id="input-3" maxlength="1" type="number" />
<input id="input-4" maxlength="1" type="number" />
jQuery
$("input").bind("paste", function(e){
var pastedData = e.originalEvent.clipboardData.getData('text');
var num_array = [];
num_array = pastedData.toString(10).replace(/\D/g, '0').split('').map(Number); // creates array of numbers
for(var a = 0; a < 4; a++) { // Since I have 4 input boxes to fill in
var pos = a+1;
event.preventDefault();
$('#input-'+pos).val(num_array[a]);
}
});
You're going to have to right some custom code. You may have to remove the maxlength property and use javascript to enforce the limit of one number per input.
As dbasemane suggests, you can listen for a paste event. You can listen to keyup events too to allow the user to type out numbers without having to switch to the next input.
Here is one possible solution:
function handleCharacter(event) {
var $input = $(this),
index = getIndex($input),
digit = $input.val().slice(0,1),
rest = $input.val().slice(1),
$next;
if (rest.length > 0) {
$input.val(digit); // trim input value to just one character
$next = $('.def-txt-input[name="chars['+ (index + 1) +']"]');
if ($next.length > 0) {
$next.val(rest); // push the rest of the value into the next input
$next.focus();
handleCharacter.call($next, event); // run the same code on the next input
}
}
}
function handleBackspace(event) {
var $input = $(this),
index = getIndex($input),
$prev;
// if the user pressed backspace and the input is empty
if (event.which === 8 && !$(this).val()) {
$prev = $('.def-txt-input[name="chars['+ (index - 1) +']"]');
$prev.focus();
}
}
function getIndex($input) {
return parseInt($input.attr('name').split(/[\[\]]/)[1], 10);
}
$('.def-txt-input')
.on('keyup paste', handleCharacter)
.on('keydown', handleBackspace);
I have this code set up on jsfiddle, so you can take a look at how it runs: http://jsfiddle.net/hallettj/Kcyna/