The script below works fine for the first div with the .inp class, it doesn't work for the second block with the same class. I broke my head trying to figure out why this is happening and how to make it work, while NOT ADDING new classes or IDs to the second div.
document.querySelector("input").focus();
document.querySelector(".inp").addEventListener("input", function({ target, data }){
// Exclude non-numeric characters (if a value has been entered)
data && ( target.value = data.replace(/[^0-9]/g,'') );
const hasValue = target.value !== "";
const hasSibling = target.nextElementSibling;
const hasSiblingInput = hasSibling && target.nextElementSibling.nodeName === "INPUT";
if ( hasValue && hasSiblingInput ){
target.nextElementSibling.focus();
}
});
.inp input {
display: inline-block;
width: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="inp">
<input type="text" name="digit1" />
<input type="text" name="digit2" />
<input type="text" name="digit3" />
<input type="text" name="digit4" />
<input type="text" name="digit5" />
</div>
<div class="inp">
<input type="text" name="digit1" />
<input type="text" name="digit2" />
<input type="text" name="digit3" />
<input type="text" name="digit4" />
<input type="text" name="digit5" />
</div>
Using (document|element).querySelector will give the first element which matches the query.
You can user (document|element).querySelectorAll instead in this scenario.
document.querySelector("input").focus();
document.querySelectorAll(".inp").forEach(element=>element.addEventListener("input", function({ target, data }){
// Exclude non-numeric characters (if a value has been entered)
data && ( target.value = data.replace(/[^0-9]/g,'') );
const hasValue = target.value !== "";
const hasSibling = target.nextElementSibling;
const hasSiblingInput = hasSibling && target.nextElementSibling.nodeName === "INPUT";
if ( hasValue && hasSiblingInput ){
target.nextElementSibling.focus();
}
}))
.inp input {
display: inline-block;
width: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="inp">
<input type="text" name="digit1" />
<input type="text" name="digit2" />
<input type="text" name="digit3" />
<input type="text" name="digit4" />
<input type="text" name="digit5" />
</div>
<div class="inp">
<input type="text" name="digit1" />
<input type="text" name="digit2" />
<input type="text" name="digit3" />
<input type="text" name="digit4" />
<input type="text" name="digit5" />
</div>
Here you go:
document.querySelector("input").focus();
document.querySelectorAll(".inp").forEach(inp => {
inp.addEventListener("input", function({ target, data }){
// Exclude non-numeric characters (if a value has been entered)
data && ( target.value = data.replace(/[^0-9]/g,'') );
const hasValue = target.value !== "";
const hasSibling = target.nextElementSibling;
const hasSiblingInput = hasSibling && target.nextElementSibling.nodeName === "INPUT";
if ( hasValue && hasSiblingInput ){
target.nextElementSibling.focus();
}
});
})
.inp input {
display: inline-block;
width: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="inp">
<input type="text" name="digit1" />
<input type="text" name="digit2" />
<input type="text" name="digit3" />
<input type="text" name="digit4" />
<input type="text" name="digit5" />
</div>
<div class="inp">
<input type="text" name="digit1" />
<input type="text" name="digit2" />
<input type="text" name="digit3" />
<input type="text" name="digit4" />
<input type="text" name="digit5" />
</div>
As Pointy mentioned querySelector() method can only be used to access a single element while querySelectorAll() method can be used to access all elements which match with a specified CSS selector.
.querySelector will work only for the first element it finds, you should use .querySelectorAll instead. It will return a node list of all selectors with your class.
Then you can iterate with a loop through all of them and add the event listener.
Related
I want to display user inputs and render them as new inputs are in. But currently, I can't seem to find a way to store the ratio values of multiple selections. I have tried "bind.(this)" and etc. None worked :(
Here's my code
import React, { Component } from "react";
class Input extends Component {
state = {
nameItems: [],
ageItems: [],
statusItems: [],
nameInput: '',
ageInput: '',
statusInput: ''
}
nameChangeHandler = ({target:{value}}) => this.setState({
nameInput: value
})
ageChangeHandler = ({target:{value}}) => this.setState({
ageInput: value
})
submitHandler = e =>{
e.preventDefault()
this.setState({
nameItems: [...this.state.nameItems, this.state.nameInput],
ageItems: [...this.state.ageItems, this.state.ageInput],
statusItems: [...this.state.statusItems, this.state.statusInput],
nameInput: '',
ageInput: '',
statusInput: ''
})
}
render() {
return (
<div>
<h1>User signup form</h1>
<form onSubmit={this.submitHandler}>
<label for="name">Name:</label><br />
<input type="text" id="name" name="name" value={this.state.nameInput} onChange={this.nameChangeHandler} /><br />
<label for="age">Age:</label><br />
<input type="number" id="age" name="age" value={this.state.ageInput} onChange={this.ageChangeHandler}/><br />
<div class="schoolYear">
<p>Your status:</p>
<input type="radio" id="freshman" name="status" value="freshman" />
<label for="freshman">Freshman</label><br />
<input type="radio" id="css" name="status" value="sophomore" />
<label for="sophomore">Sophomore</label><br />
<input type="radio" id="junior" name="status" value="junior" />
<label for="junior">Junior</label><br />
<input type="radio" id="senior" name="status" value="senior" />
<label for="senior">Senior</label><br />
</div>
<input class="submit" type="submit" value="Submit" />
<ul>
{
this.state.nameItems.map((key) => <li>{key}</li>)
}
{
this.state.ageItems.map((key) => <li>{key}</li>)
}
{
this.state.statusItems.map((key) => <li>{key}</li>)
}
</ul>
</form>
</div>
)
}
}
export default Input;
I have tried using the onChange on each individual option and the whole div but still can seem to obtain the radio value. Also when I tried setting "checked" the whole program seems to end up in a loop.
Just Copied Your code .
First of All , if you want to multiple select radio , don't name it as the same.
<div class="schoolYear">
<p>Your status:</p>
<input type="radio" id="freshman" name="freshman" value="freshman" onChange={(event)=>{setStatus((prev)=>[...prev,event.currentTarget.value])}}/>
<label for="freshman">Freshman</label><br />
<input type="radio" id="css" name="css" value="sophomore" onChange={(event)=>{setStatus((prev)=>[...prev,event.currentTarget.value])}}/>
<label for="sophomore">Sophomore</label><br />
<input type="radio" id="junior" name="junior" value="junior" onChange={(event)=>{setStatus((prev)=>[...prev,event.currentTarget.value])}}/>
<label for="junior">Junior</label><br />
<input type="radio" id="senior" name="senior" value="senior" onChange={(event)=>{setStatus((prev)=>[...prev,event.currentTarget.value])}}/>
<label for="senior">Senior</label><br />
</div>
how to find all duplicate ids when the page is relaod:
Let's say we have html like this:
<input type="radio" id="name" />
<input type="radio" id="name" />
<input type="radio" id="name" />
<input type="radio" id="last" />
<input type="radio" id="last" />
The idea is to find duplicate ids and add +1 or something like that:
What I want to achieve is:
<input type="radio" id="name1" />
<input type="radio" id="name2" />
<input type="radio" id="name3" />
<input type="radio" id="last1" />
<input type="radio" id="last2" />
JS
$('[id]').each(function(){
var ids = $('[id="'+this.id+'"]');
if(ids.length>1 && ids[0]==this)
$(this).attr('id', $(this).attr('id') + i);
});
Any ideas? Thank you all.
I would strongly recommend you serve valid HTML rather than manipulating Ids.
However, You are were close as attribute value selector may return multiple elements, You need to iterate the matching elements
var handled = [];
$('[id]').each(function() {
if (handled.includes(this.id)) {
return;
}
var elemets = $('[id="' + this.id + '"]');
if (elemets.length > 1) {
handled.push(elemets.attr('id'));
elemets.attr('id', function(index, v) {
return v + (index+1);
});
}
});
//For Readablity
$('[id]').each(function(){
console.log(this.outerHTML)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="radio" id="name" />
<input type="radio" id="name" />
<input type="radio" id="name" />
<input type="radio" id="last" />
<input type="radio" id="last" />
Try like this.
var allId = [];
var data = [];
$('[id]').each(function(){
var ids = $('[id="'+this.id+'"]');
if(allId.indexOf(this.id) < 0){
data[this.id] = 1;
allId.push(this.id);
} else {
data[this.id]++;
}
$(this).attr('id', $(this).attr('id') + data[this.id]);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="radio" id="name" />
<input type="radio" id="name" />
<input type="radio" id="name" />
<input type="radio" id="last" />
<input type="radio" id="last" />
No need for jQuery:
const ids = {}
document.querySelectorAll('[id]').forEach(node => {
if (ids[node.id] !== undefined) {
ids[node.id] += 1
} else {
ids[node.id] = 1
}
node.id = `${node.id}${ids[node.id]}`
})
document.querySelectorAll('[id]').forEach(node => console.log(node))
<input type="radio" id="name" />
<input type="radio" id="name" />
<input type="radio" id="name" />
<input type="radio" id="last" />
<input type="radio" id="last" />
try this
var i = 0;
('[id]').each(function(){
var allIds = $('[id^="'+this.id+'"]').length
var ids = $('[id="'+this.id+'"]');
if(ids.length>1 && ids[0]==this)
var i = allIds - ids.length + 1
$(this).attr('id', $(this).attr('id') + i++);
})
var a = [];
var i =0;
jQuery('[id]').each(function(){
if(a.indexOf(this.id) !== -1){ //checks if id exists in array
i++;
}
else{
i = 1;
a.push(this.id);
}
jQuery(this).attr('id', jQuery(this).attr('id') + i);
});
Explaination : I am storing each new id in array. At each iteration it checks whether the id is repeated, if so then the attribute is incremented to 1.
I've this small form in which the 1st field(title) is required by default. The 2nd and the 3rd are required only in a specific condition.
Case-I: If tool name is filled out, both tool name & tool URL become required.
Case-II: If tool URL is filled out, both tool name & tool URL become required.
I'm not sure it is working as expected.
Could you please help me correct my code?
$(document).ready(function(){
articleTitle = $('#title').val();
toolName = $('#toolName').val().trim();
toolURL = $('#toolURL').val();
if(((toolName.length>0)&&(toolURL==="")) || ((toolName.length<=0)&&(toolURL!==""))){
$('#toolName').prop('required', true);
$('#toolURL').prop('required' , true);
} else {
$('#toolName').prop('required', false);
$('#toolURL').prop('required', false);
}
$("#myForm").submit(function(){
sayHello();
return false;
});
});
label {
float: left;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<form id="myForm">
<label for="title">Title:</label> <input type="text" id="title" required> <br /><br />
<label for="toolName">Tool Name: </label><input type="text" id="toolName"> <br /> <br />
<label for="toolURL">Tool URL: </label><input type="url" id="toolURL"> <br /> <br />
<button>Submit</button>
</form>
You can simplify your code quite a bit, please see the comments for a description.
var $toolName = $('#toolName')
var $toolURL = $('#toolURL')
var $toolInputs = $($toolName).add($toolURL)
function sayHelloToMyLittleFriend() {
alert('sup! form was submitted')
}
$toolInputs.on('change', function(e) {
var toolName = $toolName.val()
var toolURL = $toolURL.val()
$toolInputs.prop('required', toolName || toolURL)
})
$('form').submit(function(e) {
var toolName = $toolName.val()
var toolURL = $toolURL.val()
var bothFilled = !!toolName && !!toolURL
var noneFilled = !toolName && !toolURL
if (bothFilled || noneFilled) {
sayHelloToMyLittleFriend()
return true
}
return false
})
label {
float: left;
width: 100px;
}
/* this will show what element has the required attribute */
[required] {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<form id="myForm">
<label for="title">Title:</label> <input type="text" id="title" required> <br /><br />
<label for="toolName">Tool Name: </label><input type="text" id="toolName"> <br /> <br />
<label for="toolURL">Tool URL: </label><input type="url" id="toolURL"> <br /> <br />
<button>Submit</button>
</form>
Here is a straightforward approach using library-less javascript (rather than jQuery).
(Albeit, you'll see that it's very similar to the jQuery).
Whenever data is entered into or removed from the form, the form inputs are checked and, as appropriate, the required attributes are added or removed.
var myForm = document.getElementById('myForm');
var toolName = document.getElementById('toolName');
var toolURL = document.getElementById('toolURL');
function checkInputs() {
if ((toolName.value !== '') || (toolURL.value !== '')) {
toolName.setAttribute('required','required');
toolURL.setAttribute('required','required');
}
if ((toolName.value === '') && (toolURL.value === '')) {
toolName.removeAttribute('required');
toolURL.removeAttribute('required');
}
}
myForm.addEventListener('keyup', checkInputs, false);
<form id="myForm">
<label for="title">Title:</label> <input type="text" id="title" required> <br /><br />
<label for="toolName">Tool Name: </label><input type="text" id="toolName"> <br /> <br />
<label for="toolURL">Tool URL: </label><input type="url" id="toolURL"> <br /> <br />
<input type="submit" value="Submit" />
</form>
I have a lot of elements which are used identical class-name. Now I need to calculate the number of selected items.
For e.g. something like this: (however this example doesn't work correctly)
$("#btn").click(function(){
if($(".necessarily").val() == ''){
$(".necessarily").css('border','1px solid red');
}
// also I want the number of input.necessarily which are empty
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<form name="frm" action="#">
<input name="first-name" class="necessarily" type="text" /><br><br>
<input name="last-name" class="necessarily" type="text" /><br><br>
<input name="email" class="necessarily" type="email" /><br><br>
<input name="password" class="necessarily" type="password" /><br><br>
<input name="address" class="anything" type="text" /><br><br>
<input name="btn" id="btn" type="submit" value="Register" />
</form>
Now I want the number of those inputs which are empty ..., How can I calculate that?
.val() method returns .value property of the first element in the collection. You can filter the empty inputs using the .filter() method and read the .length property of the filtered collection:
var $empty = $(".necessarily").filter(function() {
// you can use the `$.trim` method for trimming whitespaces
// return $.trim(this.value).length === 0;
return this.value.length === 0;
});
if ( $empty.length > 0 ) {
}
If you want to add a border to the empty fields you can declare a CSS class and use the .removeClass and .addClass methods:
CSS:
.red_border {
border: 1px solid red;
}
JavaScript:
var $empty = $(".necessarily").removeClass('red_border').filter(function() {
return this.value.length === 0;
}).addClass('red_border');
You'd do better looking at the HTML5 Contraint API rather than doing what you're currently doing, which is a more manual and time-consuming way.
Instead of giving each field a class 'necessarily' (sidenote: the word you need is 'necessary', not 'necessarily', or, better still, 'required') use the required attribute. So:
<input name="last-name" required type="text" />
Then in your jQuery you can target empty fields with:
$('input:invalid').css('border', 'solid 1px red');
If all you're doing is highlighting bad fields, you don't even need JavaScript for this. You can do the same thing via CSS:
input:invalid { border: solid 1px red; }
The only problem with that is the styling will be showed even before the user has filled out the form, which is almost never desirable. You could get round this by logging, via JS, when the form is submitted, and only then activating the styles:
JS:
$('form').on('submit', function() { $(this).addClass('show-errors'); });
CSS:
.show-errors input:invalid { border: solid 1px red; }
Try this code:
$("#btn").click(function(){
var selectedcount = $(".necessarily").length; //no. of elements with necessarily class name
var emptyInputCount=0;
$(".necessarily").each(function(){
if($(this).val() == ''){
emptyInputCount++;
}
});
Try with each loop on the target elements.
$(function() {
$("#btn").click(function() {
var i = 0;
$(".necessarily").each(function() {
if ($(this).val() == "") {
$(this).css('border', '1px solid red');
i++;
}
});
alert(i); //Number of input element with no value
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<form name="frm" action="#">
<input name="first-name" class="necessarily" type="text" />
<br>
<br>
<input name="last-name" class="necessarily" type="text" />
<br>
<br>
<input name="email" class="necessarily" type="email" />
<br>
<br>
<input name="password" class="necessarily" type="password" />
<br>
<br>
<input name="address" class="anything" type="text" />
<br>
<br>
<input name="btn" id="btn" type="submit" value="Register" />
</form>
Hope this helps!
You can use filter() like following example bellow.
var empty_inputs = $('.necessarily').filter(function(){
return $(this).val()=='';
});
empty_inputs.length will return 3 in my example.
Hope this helps.
var empty_inputs = $('.necessarily').filter(function(){
return $(this).val()=='';
});
console.log(empty_inputs.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input name="first-name" class="necessarily" type="text" /><br><br>
<input name="last-name" class="necessarily" type="text" /><br><br>
<input name="email" class="necessarily" type="email" value="Register"/><br><br>
<input name="password" class="necessarily" type="password" /><br><br>
<input name="address" class="anything" type="text" value="Register"/><br><br>
<input name="btn" id="btn" type="submit" value="Register" />
Hope this helps.
You need to:
query all elements by className
filter the jQuery Collection in order to keep only the elements that have no value
doSomethingElse
so, this maybe could help you:
function CheckEmptyCtrl($) {
'use strict';
var self = this;
self.target = $('.necessarily');
self.empty = self.target.filter(function(index, item) {
return !($(item).val().trim());
});
$('#result').append(self.empty.length + ' elements have no values.');
console.log(self.empty.length, self.empty);
}
jQuery(document).ready(CheckEmptyCtrl);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<div id="result"></div>
<form name="frm" action="#">
<input name="first-name" class="necessarily" type="text" value="notEmpty" /><br><br>
<input name="last-name" class="necessarily" type="text" /><br><br>
<input name="email" class="necessarily" type="email" /><br><br>
<input name="password" class="necessarily" type="password" /><br><br>
<input name="address" class="anything" type="text" /><br><br>
<input name="btn" id="btn" type="submit" value="Register" />
</form>
You need to loop over the all of the inputs and count how many are empty. In the same loop you can also count the number of .necessarily inputs which are empty.
This example will output the result to the .result span.
$("#btn").click(function() {
var inputs = $("form input");
var emptyNecessarilyCount = 0;
var totalEmpty = 0
inputs.each(function() {
if ($(this).val() == "") {
totalEmpty++;
if ($(this).hasClass('necessarily')) {
emptyNecessarilyCount++;
}
}
});
$('.result').append("Total: " + totalEmpty);
$('.result2').append("Necessarily: " + emptyNecessarilyCount);
});
span {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name="frm" action="#">
<input name="first-name" class="necessarily" type="text" />
<br>
<input name="last-name" class="necessarily" type="text" />
<br>
<input name="email" class="necessarily" type="email" />
<br>
<input name="password" class="necessarily" type="password" />
<br>
<input name="address" class="anything" type="text" />
<br>
<input name="btn" id="btn" type="submit" value="Register" />
<span class="result"></span>
<span class="result2"></span>
</form>
When I try to run the code below, and step into it in the browser debugger, the length it's showing me is 1 or higher, yet it still drops into this block as if it were evaluated as true...am I missing something here?
function checkEmpty() {
var empty = false;
$('form input:text').each(function () {
console.log($(this).val())
if ($(this).val().length === 0) {
empty = true;
}
});
if (empty) {
$('#btnContinueCheckout1').attr('disabled', 'disabled');
$('#btnContinueCheckout2').attr('disabled', 'disabled');
} else {
$('#btnContinueCheckout1').removeAttr('disabled');
$('#btnContinueCheckout2').removeAttr('disabled');
}
}
HTML: (these are the input fields, and they are wrapped around a form, and have 2 checkout buttons that are not shown)
<br />
<br />
<label><strong>Full Name: </strong></label>
<input type="text" required="required" onkeyup="checkEmpty()" name="FullName" style="width: 235px;" /><br />
<br />
<label><strong>Mailing Address: </strong></label>
<input type="text" required="required" name="Address" onkeyup="checkEmpty()" style="width: 235px;" /><br />
<br />
<label><strong>Email: </strong></label>
<input type="text" required="required" style="width: 235px;" name="Email" onkeyup="checkEmpty()" /><br />
<br />
<label><strong>Phone Number: </strong></label>
<input type="text" required="required" name="Phone" onkeyup="checkEmpty()" />
Try this example code in a blank html page with jQuery linked:
<html>
<head>
<title>Example</title>
<script type="text/javascript" src="jquery.min.js"></script>
</head>
<body>
<form>
<label><strong>Full Name: </strong></label>
<input type="text" required="required" onkeyup="checkEmpty()" name="FullName" style="width: 235px;" /><br />
<br />
<label><strong>Mailing Address: </strong></label>
<input type="text" required="required" name="Address" onkeyup="checkEmpty()" style="width: 235px;" /><br />
<br />
<label><strong>Email: </strong></label>
<input type="text" required="required" style="width: 235px;" name="Email" onkeyup="checkEmpty()" /><br />
<br />
<label><strong>Phone Number: </strong></label>
<input type="text" required="required" name="Phone" onkeyup="checkEmpty()" />
<input type="button" id="checkbutton" value="deactivated" disabled/>
</form>
</body>
<script type="text/javascript">
function checkEmpty() {
var empty = false;
$('form input:text').each(function () {
console.log($(this).val());
if ($(this).val().length === 0) {
empty = true;
}
});
if (empty) {
$('#checkbutton').prop('disabled', 'disabled');
} else {
$('#checkbutton').prop('disabled', '');
}
console.log('count of textfields: ' + $('form input:text').length);
}
</script>
</html>
It works 100% for me. Look at the console to check the count for the textfields. If it's more then you expect, check your html if you have missed one. If all fields are filled, the button will be activated.
The problem is that you're assigning empty=true; when you read one input field, but then the loop will keep going and check further input fields. This means that if the first field is empty, but the second one isn't empty, your loop will not work. Try to break out of the .each() loop as soon as you find the first empty input.
function checkEmpty() {
var empty = false;
$('form input:text').each(function () {
console.log($(this).val()); // Also, you forgot the ; here
if ($(this).val().length === 0) {
empty = true;
return false; // Will break out of the .each() loop
}
});
if (empty) {
$('#btnContinueCheckout1').attr('disabled', 'disabled');
$('#btnContinueCheckout2').attr('disabled', 'disabled');
} else {
$('#btnContinueCheckout1').removeAttr('disabled');
$('#btnContinueCheckout2').removeAttr('disabled');
}
}